SQL Server執行緒事務與死鎖的一次例項分析

2021-08-31 16:04:57 字數 2578 閱讀 2314

背景

故事是這樣的,在乙個系統試執行階段,發現了乙個資料庫死鎖的異常.具體的錯誤是 :

"xx寫入異!事務與另乙個程序鎖死在鎖|通訊緩衝區資源上,並且一杯選做死鎖犧牲品"
按字面的意思理解也很簡單.多個執行緒同時運算元據庫死鎖導致了問題.這裡需要了解到非常多資料庫相關鎖的知識,具體請看有些人寫的非常好的文件:

資料庫系統原理

microsoft sql server中的事務與併發詳解

正文業務其實也比較簡單,這張表是個批處理表,有時候需要批量更新資料;sql語句非常簡單

update my_table set colume1 = '***' where colum2=@para
看似非常簡單的語句其實裡面隱藏著非常多的知識點,如 主鍵,索引,全表掃瞄,x(寫)鎖,ix(意向)鎖,行鎖,頁鎖,表鎖,等;我們乙個乙個情況分析,看那些知識點在什麼情況下會發生什麼事情

這是乙個update操作,缺省會開啟x鎖,

預設開啟查詢出資料的行鎖x鎖,整個table 的ix意向鎖

如果column2是主鍵

當多執行緒再次執行是,如果@para與其他執行緒的value不相等,不死鎖

如果@para與其他執行緒的value相等,死鎖

如果column2不是主鍵,但是是索引,執行效果與主鍵相同

相同的前提條件是,查詢條件掃瞄時走了索引

如果column2既不是主鍵,又不是索引

同樣,依然是把查詢出來的資料上x鎖,但是第二個執行緒來查詢的時候,依然會造成鎖的等待,由於沒有索引,資料更新的時候需要全表掃瞄,但由於一些資料在x鎖上,所以無法讀取,此時相當於表鎖了;

以上問題,在開發中也考慮到了,所以我們的程式給column2欄位加了索引,而且我們的程式基本上不會由多個執行緒同時跟新一條資料,理論上不應該頻繁發生死鎖的問題(大概兩天會出現一次死鎖的錯誤)

這個時候需要與一些資料庫本身的特性可能有關了,這裡是sql server 資料庫,開啟模擬情況,並列印加鎖日誌:

-- lock info 

select -- use * to explore

request_session_id as spid,

resource_type as restype,

resource_database_id as dbid,

db_name(resource_database_id) as dbname,

resource_description as res,

resource_associated_entity_id as resid,

request_mode as mode,

request_status as status

from sys.dm_tran_locks

where db_name(resource_database_id)='mydb'

-- kill 59;

模擬語句1

begin tran;

update my_table set colume1 = '***' where colum2='aaa'

waitfor delay '00:00:10'; -- 模擬事務進行了10秒鐘後提交

commit tran;

模擬語句2

begin tran;

update my_table set colume1 = '***' where colum2='bbb'

commit tran;

兩個模擬語句在兩個視窗同時執行,然後檢視lock情況,執行多次發現都與預計的情況相符,理論上不會傳送死鎖的情況. 第一條語句查詢出來的資料上的都是x鎖,同時也有page 的ix鎖,object(表)的ix鎖,第二條查詢的時候,通過索引查詢,不需要等待第乙個事務;

很迷茫,無論是正式環境還是測試環境,都模擬不出來現場bug.我這裡已經模擬了10秒鐘的慢查詢,實際情況比這快很多.糾結了一上午,超出了已知知識的範圍.猜測是應該某種情況下的update操作進行了加表鎖,而不是行鎖導致的.查詢條件更改,新增null值,都不能模擬出表鎖;

問題原因

在此處沒有思路的情況下,換了一種思路去解決問題,接下去,我去分析了批處理my_table表的資料,正常情況下的column2屬性值資料應該在100條以內,但由於是試執行模擬資料,有些資料在四五千條左右,抽出乙個四五千的查詢條件,繼續進行模擬加鎖操作,經過多次模擬,此時發現了最終問題所在,當update操作的資料超出一定資料條數之後,本來預設的行鎖此時公升級成了表鎖.接下來的多執行緒等任何查詢等語句,都要等待這個執行緒釋放掉表的x鎖.問題找到了,解決起來就簡單多了;

解決方法

兩個方法,第乙個方法沒有去驗證

在update的時候指定行鎖的實現,不通過sql server的內部優化引擎

在update的時候限制每次批處理的條數(測試模擬中1500條以內,不會公升級成表鎖) 思考

除了書本上的理論知識之外,每個框架,軟體的內部優化實現不盡相同,需要在實踐中多思考多積累;

mysql沒有事務死鎖 Mysql事務與死鎖

好久沒有寫部落格了,最近工作太忙了,真的是996icu呀。想找個機會跳出來。之後我要做到work life balance!當考慮的就是資料一致性的問題時我們用就應該想到mysql的事務。但是當我們使用事務時會有很多的坑,首先我們了解一下事務的隔離界別。1 事物的隔離級別 資料庫中有四種資料隔離級別...

SQLServer 內部事務與外部事務的統一

在我們日常資料庫開發過程中,涉及到資料增刪改,無一例外都需要使用事務來控制其一致性。而對於業務邏輯比較複雜的erp mes wms等系統來說,一致性尤其重要。此時我們考慮乙個問題,儲存過程a開啟了事務,此時b由於業務需要呼叫儲存過程a,但是b又有自己的業務,也需要開啟事務。此時我們就需要考慮事務的一...

多執行緒與事務併發

多執行緒與事務併發 在實際問題中,不要在事件處理執行緒中做任何主要工作,而應當使用另外的執行緒作為工作執行緒,並允許事件處理執行緒快速地返回到處理事件等待狀態 這句話看起來非常有道理,多執行緒的優點要充分體現!那麼執行緒處理要完成的工作以及業務要處理的工作如何劃分?實際上這個問題可以歸結為控制驅動體...