Sql-Server

插入/更新死鎖

  • February 27, 2012

使用 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。但是,您將問題描述為“立即”出現,這強烈表明還有其他一些因素在起作用,我們只能在缺乏實際資訊的情況下進行推測。

當然,擷取死鎖圖並將其發佈在此處會更有用。僅討論對僵局的描述的價值有限,因為您的描述可能是事實,也可能不是事實,您的理解可能正確也可能不正確,我們的解釋可能準確也可能不准確。

引用自:https://dba.stackexchange.com/questions/14022