插入/更新死鎖
使用 SQL Server 2008 R2:
我目前正在嘗試追查我們遇到的死鎖問題的原因。不知道該轉向哪裡。這是設置。
TABLE Scores: id INT IDENTITY(1,1), first_name VARCHAR(50), last_name VARCHAR(50), player_id VARCHAR(50), score INT PRIMARY KEY/CLUSTERED INDEX: id NON-CLUSTERED INDEX: first_name, last_name INCLUDES id, player_id, score
多執行緒應用程序處理消息,然後為每條消息呼叫兩個儲存過程之一。
如果應用程序沒有處理使用者,它將呼叫一個儲存過程,將一行插入到表中。
如果應用程序已經處理了使用者,它會更新任何或所有的
first_name
,last_name
,scores
,first_name
並且last_name
player_id
不會改變。每個表中只有一行
player_id
。應用程序處理消息的執行緒是根據 player_id 選擇的,因此兩個執行緒不會同時處理同一播放器的消息。
INSERT 和 UPDATE 語句正在使用該
WITH (ROWLOCK)
指令。這是問題:
該程序導致死鎖,執行緒 1 鎖定主聚集索引,執行緒 2 鎖定非聚集索引。
我不明白為什麼會發生鎖 - UPDATE 和 INSERT 語句正在使用行鎖,並且已經過測試並證明執行緒沒有訪問相同的行。
我能做些什麼來解決這個問題?
注意事項:
必須存在兩個儲存過程,一個更新,一個插入。儘管我想切換到單個 MERGE,但這不會發生。:/
沒有死鎖痕跡就無法確認,但看起來你已經得到了答案。
該程序導致死鎖,執行緒 1 鎖定主聚集索引,執行緒 2 鎖定非聚集索引。
可能您的一個過程首先在非聚集索引上獲取共享鎖,然後是聚集索引。另一個則相反,首先在集群上獲取共享鎖,然後是非集群。
更新任何 NC 索引鍵是可能導致死鎖的更新。這是由於訪問路徑不同而導致的典型讀寫死鎖。即使您更新不同的密鑰,也不能消除衝突,因為鎖在密鑰散列上,請參閱%%lockres%% 碰撞機率魔法標記:16,777,215。但是,您將問題描述為“立即”出現,這強烈表明還有其他一些因素在起作用,我們只能在缺乏實際資訊的情況下進行推測。
當然,擷取死鎖圖並將其發佈在此處會更有用。僅討論對僵局的描述的價值有限,因為您的描述可能是事實,也可能不是事實,您的理解可能正確也可能不正確,我們的解釋可能準確也可能不准確。