Sql-Server
什麼會導致此 SQL Server 死鎖?
我有一個 node.js 腳本試圖對錶中的記錄進行地理編碼。該腳本一次選擇 100 條沒有緯度/日誌數據的記錄,使用第三方 api 對其進行地理編碼,並將結果寫入相應記錄的緯度/經度列。此腳本導致數據庫中出現死鎖錯誤,如下所示:
事務(程序 ID 69)與另一個程序在鎖資源上死鎖,並已被選為死鎖犧牲品。重新執行事務。
我設置 SQL Server Profiler 來執行跟踪和跟踪死鎖數據,並且能夠獲得其中一個死鎖圖,但我無法完全弄清楚為什麼會發生死鎖。這兩個語句都是針對同一個表中的不同記錄的更新。我檢查了隔離級別,它是
Read Committed
。雖然我沒有處理過很多數據庫死鎖,但我認為這些類型的事務不會導致死鎖。我在下麵包含了 XML,以防萬一:<deadlock-list> <deadlock victim="process25211037848"> <process-list> <process id="process25211037848" taskpriority="0" logused="0" waitresource="PAGE: 8:1:34878 " waittime="2422" ownerId="3315762" transactionname="UPDATE" lasttranstarted="2021-05-23T23:46:32.920" XDES="0x24d9e44d900" lockMode="U" schedulerid="4" kpid="7440" status="suspended" spid="65" sbid="0" ecid="4" priority="0" trancount="0" lastbatchstarted="2021-05-23T23:46:32.923" lastbatchcompleted="2021-05-23T23:46:32.380" lastattention="1900-01-01T00:00:00.380" clientapp="Node.js" hostname="PNS157" hostpid="6536" isolationlevel="read committed (2)" xactid="3315762" currentdb="8" currentdbname="DW_Staging" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056"> <executionStack> <frame procname="adhoc" line="1" stmtstart="100" stmtend="250" sqlhandle="0x02000000259d222f04b5eda0f2e0ab46a16fa9ba5cc2d8310000000000000000000000000000000000000000"> unknown </frame> <frame procname="adhoc" line="1" stmtend="236" sqlhandle="0x02000000a6f84a131709260f562f587021ed884c3ed1e86a0000000000000000000000000000000000000000"> unknown </frame> </executionStack> <inputbuf> UPDATE Members SET MbrLat = 28.03195, MbrLong = -81.09178 WHERE MemberUID = 'ID456' </inputbuf> </process> <process id="process24eae1b64e8" taskpriority="0" logused="0" waitresource="PAGE: 8:1:36694 " waittime="2422" ownerId="3315758" transactionname="UPDATE" lasttranstarted="2021-05-23T23:46:32.920" XDES="0x25206e8b900" lockMode="U" schedulerid="3" kpid="7784" status="suspended" spid="79" sbid="0" ecid="2" priority="0" trancount="0" lastbatchstarted="2021-05-23T23:46:32.920" lastbatchcompleted="2021-05-23T23:46:32.480" lastattention="1900-01-01T00:00:00.480" clientapp="Node.js" hostname="PNS157" hostpid="6536" isolationlevel="read committed (2)" xactid="3315758" currentdb="8" currentdbname="DW_Staging" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056"> <executionStack> <frame procname="adhoc" line="1" stmtstart="100" stmtend="250" sqlhandle="0x02000000d48bf12084e55043f1f9c7969865359e9737b71a0000000000000000000000000000000000000000"> unknown </frame> <frame procname="adhoc" line="1" stmtend="244" sqlhandle="0x02000000424e371e647b248bf01785555348ca7d05f180650000000000000000000000000000000000000000"> unknown </frame> </executionStack> <inputbuf> UPDATE Members SET MbrLat = 25.9510963, MbrLong = -81.1176539 WHERE MemberUID = 'ID123' </inputbuf> </process> </process-list> <resource-list> <pagelock fileid="1" pageid="34878" dbid="8" subresource="FULL" objectname="DW_Staging.dbo.Members" id="lock24ed7f99880" mode="U" associatedObjectId="72057594044678144"> <owner-list> <owner id="process24eae1b64e8" mode="U"/> </owner-list> <waiter-list> <waiter id="process25211037848" mode="U" requestType="wait"/> </waiter-list> </pagelock> <pagelock fileid="1" pageid="36694" dbid="8" subresource="FULL" objectname="DW_Staging.dbo.Members" id="lock24e383d5f00" mode="U" associatedObjectId="72057594044678144"> <owner-list> <owner id="process25211037848" mode="U"/> </owner-list> <waiter-list> <waiter id="process24eae1b64e8" mode="U" requestType="wait"/> </waiter-list> </pagelock> </resource-list> </deadlock> </deadlock-list>
誰能明白為什麼會發生這種死鎖?關於如何解決這些死鎖錯誤或我應該如何調試問題的任何建議?
更新- 回答以下問題:
- 我沒有關於 MemberUID 的索引
- 執行計劃可以在這裡找到。
因為表上沒有合適的索引,所以會進行全表掃描。
表掃描是並行的,這意味著訪問是無序的。你可以通過使用來解決這個問題
OPTION(MAXDOP 1)
,但這只是一個創可貼。**你最好的辦法是創建一個索引來服務這個查詢,**這個想法是查詢只需要對它需要的確切行進行點查找。
在不知道您有其他疑問的情況下,我只能基於此提出建議
CREATE NONCLUSTERED INDEX IX_Members_MemberUID ON Members (MemberUID) INCLUDE (MbrLat, MbrLong);
鑑於該列被稱為
MemberUID
它可能是主鍵,在這種情況下,您幾乎可以肯定地將其CLUSTERED
設為索引CREATE UNIQUE CLUSTERED INDEX CX_Members_MemberUID ON Members (MemberUID);
或更好
-- DROP CONSTRAINT the old primary key then ... ALTER TABLE Members ADD CONSTRAINT PRIMARY KEY CLUSTERED (MemberUID);