1. 程式人生 > 實用技巧 >資料庫死鎖 之 二.定位死鎖

資料庫死鎖 之 二.定位死鎖

2.獲取死鎖的資訊

這篇文章接著之前的內容,重現死鎖並獲取死鎖相關的資訊,從而幫助我們來解決死鎖;

-- 2.1 得到死鎖資訊

經過不懈的努力,在【啥是死鎖】的1.3.1中,我們終於如願的死鎖了,那我們就來分析死鎖的資訊吧,那下一步我們該怎麼做呢?怎麼得到死鎖的相關資訊,從而定位到死鎖的原因?

-- 2.1.1 SQL Profiler

通過開啟資料的Profiler監聽工具獲取死鎖的相關資訊,該方式侷限性比較大: 1.如遇到客戶的正式環境中,通過Profiler的方式效能消耗較大 2.業務場景過多,死鎖場景也不是一定可重現(當然明確了死鎖步驟除外) A.開啟Profiler,開啟Deadlock監聽; B.執行死鎖場景,復現死鎖,我們這裡就是直接執行我們模式死鎖的程式,也就是【啥是死鎖】中我們自定義的兩個儲存過程,程式碼中實現的重複呼叫


-- 2.1.2 死鎖日誌方式獲取死鎖資訊

# A. 開啟死鎖監控日誌 dbcc traceon (1222,-1) dbcc traceon (1204,-1) # 關閉死鎖監控日誌 dbcc traceoff (1222,-1) dbcc traceoff (1204,-1) # B. 等待或再次觸發死鎖,重現死鎖 # C. 檢視死鎖的日誌
exec xp_readerrorlog
這個儲存過程是有引數的,如果你沒有寫引數,他預設查詢的是sqlserve日誌編號為0(當前的日誌文件,不是當天,指的是前一一個檔案的時間節點到當前時間的所有日誌)的日誌。 如果你想選擇引數,從左往右是一共6個,如下解釋 1)日誌編號——整型,如下圖所示的編碼,一次只能指定一個編號 ,不能多個。 2)查詢的日誌型別——整型,1是sqlserver的日誌,2是sqlserver代理日誌。 3)要查詢的字串,用雙引號包著。——字串 4)要查詢的字串——字串,3和4沒有區別,也就是你規定兩個要查詢的字串,如果你只需要查詢一個,第二個寫NULL就可以。 5)查詢的開始日期——字串,格式是YYYY-MM-DD hh:mm:ss 6)查詢的結束日期——字串,格式是YYYY-MM-DD hh:mm:ss 直接給一個示例(引數一定要用雙引號引著,要不然會報錯)
exec master..xp_readerrorlog 0
,1,null,null,"2020-05-25 11:33:00","2020-05-25 11:40:00"

如下圖就是日誌儲存位置:

死鎖日誌如下: 然後通過死鎖時間獲取死鎖相關的具體資訊:
# 執行命令 exec master..xp_readerrorlog 0
Deadlock encountered .... Printing deadlock information
Wait-for graph
NULL
Node:1
PAGE: 5:1:1544                 CleanCnt:2 Mode:IX Flags: 0x3
Grant List 0:
   Owner:0x0000000389D192C0
Mode: IX Flg:0x40 Ref:0 Life:02000000 SPID:62 ECID:0 XactLockInfo: 0x0000000392CCB108 SPID: 62 ECID: 0 Statement Type: SELECT Line #: 1 Input Buf: Language Event: BEGIN TRANSACTION ;INSERT INTO TestA(Name) VALUES('張三');SELECT name FROM TestB;COMMIT; Requested by: ResType:LockOwner Stype:'OR'Xdes:0x0000000392CE2570 Mode: S SPID:63 BatchID:0 ECID:0 TaskProxy:(0x0000000376B9A638) Value:0x89d17b40 Cost:(0/228) NULL Node:2 PAGE: 5:1:664 CleanCnt:2 Mode:IX Flags: 0x3 Grant List 2: Owner:0x0000000389D1B000 Mode: IX Flg:0x40 Ref:0 Life:02000000 SPID:63 ECID:0 XactLockInfo: 0x0000000392CE25A8 SPID: 63 ECID: 0 Statement Type: SELECT Line #: 1 Input Buf: Language Event: BEGIN TRANSACTION ;INSERT INTO TestB(Name) VALUES('張三');SELECT name FROM TestA;COMMIT; Requested by: ResType:LockOwner Stype:'OR'Xdes:0x0000000392CCB0D0 Mode: S SPID:62 BatchID:0 ECID:0 TaskProxy:(0x00000003778E2638) Value:0x89d1a980 Cost:(0/228) NULL Victim Resource Owner: ResType:LockOwner Stype:'OR'Xdes:0x0000000392CE2570 Mode: S SPID:63 BatchID:0 ECID:0 TaskProxy:(0x0000000376B9A638) Value:0x89d17b40 Cost:(0/228) deadlock-list deadlock victim=process37cb164e8 process-list process id=process37cb164e8 taskpriority=0 logused=228 waitresource=PAGE: 5:1:1544 waittime=2128 ownerId=1813485 transactionname=user_transaction lasttranstarted=2020-05-25T12:30:46.770 XDES=0x392ce2570 lockMode=S schedulerid=6 kpid=10664 status=suspended spid=63 sbid=0 ecid=0 priority=0 trancount=1 lastbatchstarted=2020-05-25T12:30:46.767 lastbatchcompleted=2020-05-25T12:30:46.757 lastattention=1900-01-01T00:00:00.757 clientapp=.Net SqlClient Data Provider hostname=DESKTOP-9LP3PP7 hostpid=10844 loginname=sa isolationlevel=read committed (2) xactid=1813485 currentdb=5 lockTimeout=4294967295 clientoption1=671088672 clientoption2=128056 executionStack frame procname=adhoc line=1 stmtstart=112 stmtend=154 sqlhandle=0x020000002d23e01cc638e358ac37629c45bc6abb5c644b220000000000000000000000000000000000000000 unknown inputbuf BEGIN TRANSACTION ;INSERT INTO TestB(Name) VALUES('張三');SELECT name FROM TestA;COMMIT; process id=process37db3b468 taskpriority=0 logused=228 waitresource=PAGE: 5:1:664 waittime=2198 ownerId=1813486 transactionname=user_transaction lasttranstarted=2020-05-25T12:30:46.803 XDES=0x392ccb0d0 lockMode=S schedulerid=1 kpid=912 status=suspended spid=62 sbid=0 ecid=0 priority=0 trancount=1 lastbatchstarted=2020-05-25T12:30:46.803 lastbatchcompleted=2020-05-25T12:30:46.807 lastattention=1900-01-01T00:00:00.807 clientapp=.Net SqlClient Data Provider hostname=DESKTOP-9LP3PP7 hostpid=10844 loginname=sa isolationlevel=read committed (2) xactid=1813486 currentdb=5 lockTimeout=4294967295 clientoption1=671088672 clientoption2=128056 executionStack frame procname=adhoc line=1 stmtstart=112 stmtend=154 sqlhandle=0x02000000d1985a2ff61043a378822d6e246dbe147d5962180000000000000000000000000000000000000000 unknown inputbuf BEGIN TRANSACTION ;INSERT INTO TestA(Name) VALUES('張三');SELECT name FROM TestB;COMMIT; resource-list pagelock fileid=1 pageid=1544 dbid=5 subresource=FULL objectname=資料庫.dbo.TestA id=lock3891fe680 mode=IX associatedObjectId=72057594456965120 owner-list owner id=process37db3b468 mode=IX waiter-list waiter id=process37cb164e8 mode=S requestType=wait pagelock fileid=1 pageid=664 dbid=5 subresource=FULL objectname=資料庫.dbo.TestB id=lock3956b5080 mode=IX associatedObjectId=72057594457030656 owner-list owner id=process37cb164e8 mode=IX waiter-list waiter id=process37db3b468 mode=S requestType=wait

通過這篇文章,我們已經找到死鎖的資訊了,那下面我們就要開始解讀這些資訊,從而指導我們來解決死鎖;