SQL Server 死鎖問題的分析

摘要:?SQL Server死鎖的捕獲、分析和解決方法。

一、什么是死鎖?

簡單來說,我和你,金鎖和銀鎖。

我拿著金鎖,我需要再拿到銀鎖,才能完成任務(wù),

你拿著銀鎖,你需要再拿到金鎖,才能完成任務(wù)。

我拿不到銀鎖,你拿不到金鎖,這就形成死鎖了。

二、死鎖發(fā)生后,SQL Server怎么處理?

SQL Server內(nèi)置有死鎖偵測和處理機(jī)制,每5S會檢測一次,如果有死鎖,就會評估下哪個事務(wù)回滾的開銷比較低,將其kill掉,然后反饋1205錯誤。

實(shí)際上并沒有這么簡單,比如可以設(shè)置會話的優(yōu)先級,優(yōu)先級越低,被選為犧牲品的可能性就越大。

三、死鎖發(fā)生后怎么處理?

捕獲死鎖>>分析死鎖>>解決方案

先模擬獲取死鎖的demo

/*建表*/CREATETABLE[dbo].[deadlockTest]([id][int]IDENTITY(1,1)NOTNULL,[userid][varchar](10)NULL,[num][int]NULL,CONSTRAINT[PK_deadlockTest]PRIMARYKEYCLUSTERED([id]ASC)WITH(PAD_INDEX=OFF,STATISTICS_NORECOMPUTE=OFF,IGNORE_DUP_KEY=OFF,ALLOW_ROW_LOCKS=ON,ALLOW_PAGE_LOCKS=ON)ON[PRIMARY])ON[PRIMARY]/*建索引*/createindexix_useridondeadlockTest(userid)/*生成測試數(shù)據(jù)*/insertintodeadlockTestselect1,1insertintodeadlockTestselect2,2/*事務(wù)1*/--我begintranupdatedeadlockTestsetnum=100whereid=1--金鎖updatedeadlockTestsetnum=100whereid=2--銀鎖? ?。∽⒁膺@一句執(zhí)行事務(wù)2后,回來再執(zhí)行/*事務(wù)2*/--你begintranupdatedeadlockTestsetnum=100whereid=2--銀鎖updatedeadlockTestsetnum=100whereid=1--金鎖

結(jié)果:

1、捕獲死鎖,方法較多,常用的兩種方法

>>打開跟蹤標(biāo)志 1222[RDS不支持],可以從SQL SERVER日志中獲取到死鎖信息

DBCC TRACEON(1222,-1)

>>SQL Server Profiler抓取

2、分析死鎖

完整的死鎖信息【敏感信息XXX脫敏】綠底和紅字是分析文字

第一部分:犧牲品

?

第二部分:進(jìn)程信息

?

<process id="process40fb278"taskpriority="0" logused="144"?waitresource="KEY: 5:72057594039238656 (61a06abd401c)"?waittime="3421" ownerId="83492" transactionname="user_transaction" lasttranstarted="2018-01-31T00:19:12.110" XDES="0xa9ac290" lockMode="X" schedulerid="4" kpid="4312" status="suspended" spid="53" sbid="0" ecid="0" priority="0"?trancount="2"?lastbatchstarted="2018-01-31T00:19:17.500" lastbatchcompleted="2018-01-31T00:19:12.110" lastattention="1900-01-01T00:00:00.110" clientapp="Microsoft SQL Server Management Studio - 查詢" hostname="ALI-XXX" hostpid="13556" loginname="HZ\XXX" isolationlevel="read committed (2)" xactid="83492"?currentdb="5"?lockTimeout="4294967295" clientoption1="671090784" clientoption2="390200">

? ?


UPDATE [deadlockTest] set [num] = @1? WHERE [id]=@2???


update deadlockTest set num=100 where id=2??


? ?

update deadlockTest set num=100 where id=2??


<process id="process40eb468"?taskpriority="0" logused="144"?waitresource="KEY: 5:72057594039238656 (8194443284a0)"?waittime="6676" ownerId="83494" transactionname="user_transaction" lasttranstarted="2018-01-31T00:19:14.247" XDES="0x4126378" lockMode="X" schedulerid="2" kpid="4340" status="suspended" spid="52" sbid="0" ecid="0" priority="0"?trancount="2"?lastbatchstarted="2018-01-31T00:19:14.247" lastbatchcompleted="2018-01-31T00:19:08.843" lastattention="1900-01-01T00:00:00.843" clientapp="Microsoft SQL Server Management Studio - 查詢" hostname="ALI-XXX" hostpid="13556" loginname="HZ\XXX" isolationlevel="read committed (2)" xactid="83494" currentdb="5" lockTimeout="4294967295" clientoption1="671090784" clientoption2="390200">

? ?


UPDATE [deadlockTest] set [num] = @1? WHERE [id]=@2? ??


update deadlockTest set num=100 where id=1

?--commit? ? ?


? ?

begin tran?

update deadlockTest set num=100 where id=2

update deadlockTest set num=100 where id=1

--commit?



第三部分:資源信息

?

hobtid="72057594039238656" dbid="5" objectname="blockTest.dbo.deadlockTest" indexname="PK_deadlockTest"?id="lock2c69480" mode="X" associatedObjectId="72057594039238656">

? ?

??


? ?

<waiter id="process40fb278" mode="X" requestType="wait"/>



? ?

? ?


? ?





根據(jù)上面的死鎖信息,可以得到:

可以看到死鎖的原因,兩個事務(wù)都想獲取對方持有資源上的X鎖進(jìn)行update,互不相讓,所以就形成了死鎖。

KEY: 5:72057594039238656? ?這個說明,鎖定的資源是KEY,數(shù)據(jù)庫是5,資源是72057594039238656

這些可以通過腳本獲取到具體的信息,但是沒有必要,第三部分resource-list完全可以獲取到,數(shù)據(jù)庫是blockTest,表示deadlockTest,鍵是PK_deadlockTest

解決方案,

由于兩個事務(wù)執(zhí)行的SQL順序相反,所以產(chǎn)生了這種情況,該case的解法就是將兩個事務(wù)SQL執(zhí)行順序設(shè)為一致即可。

四、死鎖總結(jié)

死鎖不能完全避免,只能是盡量降低,一般常用的方法【降低互斥發(fā)生的風(fēng)險、減少鎖的申請數(shù)量、降低鎖持有的時間】:

1、按相同順序訪問對象

這樣就會降低互斥發(fā)生的風(fēng)險,也就是DEMO的這個案例

2、事務(wù)盡量簡短

因?yàn)槭聞?wù)commit后,才會釋放該事務(wù)中持有的鎖,所以事務(wù)越簡短,持有鎖的時間就會越短,從而降低死鎖發(fā)生的概率。

3、優(yōu)化SQL,盡量避免table scan,index scan這種方式

這樣SQL執(zhí)行掃描/查找的數(shù)量就會減少,從而達(dá)到減少申請鎖的數(shù)量的目的。

4、事務(wù)中避免與用戶的交互

這個會大大增長鎖持有的時間,DEMO的這個案例,也可以理解為與用戶交互了,因?yàn)槭聞?wù)1第二個update,測試時是等待第二個事務(wù)執(zhí)行后,再去手動執(zhí)行的。

還有一個方法,就是降低事務(wù)的隔離級別,低隔離級別S鎖的持有時間會較短,但是這個方法大部分情況下是不可能采納的。

版權(quán)聲明:本文內(nèi)容由互聯(lián)網(wǎng)用戶自發(fā)貢獻(xiàn),版權(quán)歸作者所有,本社區(qū)不擁有所有權(quán),也不承擔(dān)相關(guān)法律責(zé)任。如果您發(fā)現(xiàn)本社區(qū)中有涉嫌抄襲的內(nèi)容,歡迎發(fā)送郵件至:yqgroup@service.aliyun.com?進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),本社區(qū)將立刻刪除涉嫌侵權(quán)內(nèi)容。

原文鏈接

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容