深入淺出解析mssql在高頻,高并發(fā)訪問(wèn)時(shí)鍵查找死鎖問(wèn)題
死鎖對(duì)于DBA或是數(shù)據(jù)庫(kù)開(kāi)發(fā)人員而言并不陌生,它的引發(fā)多種多樣,一般而言,數(shù)據(jù)庫(kù)應(yīng)用的開(kāi)發(fā)者在設(shè)計(jì)時(shí)都會(huì)有一定的考量進(jìn)而盡量避免死鎖的產(chǎn)生.但有時(shí)因?yàn)橐恍┨厥鈶?yīng)用場(chǎng)景如高頻查詢,高并發(fā)查詢下由于數(shù)據(jù)庫(kù)設(shè)計(jì)的潛在問(wèn)題,一些不易捕捉的死鎖可能出現(xiàn)從而影響業(yè)務(wù).這里為大家介紹由于設(shè)計(jì)問(wèn)題引起的鍵查找死鎖及相關(guān)的解決辦法.
這里我們?cè)跍y(cè)試的同時(shí)開(kāi)啟trace profiler跟蹤死鎖視圖(locks:deadlock graph).(當(dāng)然也可以開(kāi)啟跟蹤標(biāo)記,或者應(yīng)用擴(kuò)展事件(xevents)等捕捉死鎖)
創(chuàng)建測(cè)試對(duì)象code
create table testklup ( clskey int not null, nlskey int not null, cont1 int not null, cont2 char(3000) ) create unique clustered index inx_cls on testklup(clskey) create unique nonclustered index inx_nlcs on testklup(nlskey) include(cont1) insert into testklup select 1,1,100,'aaa' insert into testklup select 2,2,200,'bbb' insert into testklup select 3,3,300,'ccc'
開(kāi)啟會(huì)話1 模擬高頻update操作
----模擬高頻update操作
declare @i int set @i=100 while 1=1 begin update testklup set cont1=@i where clskey=1 set @i=@i+1 end
開(kāi)啟會(huì)話2 模擬高頻select操作
----模擬高頻select操作
declare @cont2 char(3000) while 1=1 begin select @cont2=cont2 from testklup where nlskey=1 end
此時(shí)開(kāi)啟會(huì)話2執(zhí)行一小段時(shí)間時(shí)我們就可以看到類(lèi)似錯(cuò)誤信息:圖1-1

圖1-1
而在我們開(kāi)啟的跟蹤中捕捉到了如下的死鎖圖.圖1-2

圖1-2
死鎖分析:可以看出由于讀進(jìn)程(108)請(qǐng)求寫(xiě)進(jìn)程(79)持有的X鎖被阻塞的同時(shí),寫(xiě)進(jìn)程(79)又申請(qǐng)讀進(jìn)程(108)鎖持有的S鎖.讀執(zhí)行計(jì)劃圖1-3,寫(xiě)執(zhí)行計(jì)劃圖1-4
(由于在默認(rèn)隔離級(jí)別下(讀提交)讀申請(qǐng)S鎖只是瞬間過(guò)程,讀完立即釋放,不會(huì)等待事務(wù)完成),所以在并發(fā),執(zhí)行頻率不高的情形下不易出現(xiàn).但我們模擬的高頻情況使得S鎖獲得頻率非常高,此時(shí)就出現(xiàn)了僅僅兩個(gè)會(huì)話,一個(gè)讀,一個(gè)寫(xiě)就造成了死鎖現(xiàn)象.

圖1-3

圖1-4
死鎖原因:讀操作中的鍵查找造成的額外鎖(聚集索引)需求
解決方案:在了解了死鎖產(chǎn)生的原因后,解決起來(lái)就比較簡(jiǎn)單了.
我們可以從以下幾個(gè)方面入手.
a 消除額外的鍵查找鎖需的鎖
b 讀操作時(shí)取消獲取鎖
a.1我們可以創(chuàng)建覆蓋索引使select語(yǔ)句中的查詢列包含在指定索引中
CREATE NONCLUSTERED INDEX [inx_nlskey_incont2] ON [dbo].[testklup] ([nlskey] ASC) INCLUDE ( [cont2])
a.2 根據(jù)查詢需求,分步執(zhí)行,通過(guò)聚集索引獲取查詢列,避免鍵查找.
declare @cont2 char(3000) declare @clskey int while 1=1 begin select @clskey=clskey from testklup where nlskey=1 select @cont2=cont2 from testklup where clskey=@clskey end
b 通過(guò)改變隔離級(jí)別,使用樂(lè)觀并發(fā)模式,讀操作時(shí)源行無(wú)需鎖
declare @cont2 char(3000) while 1=1 begin select @cont2=cont2 from testklup with(nolock) where nlskey=1 end
結(jié)束語(yǔ).我們?cè)诮鉀Q問(wèn)題時(shí),最好弄清問(wèn)題的本質(zhì)原因,通過(guò)問(wèn)題點(diǎn)尋找出適合自己的環(huán)境的解決方案再實(shí)施.
- 解決Android Studio 格式化快捷鍵和QQ 鎖鍵盤(pán)快捷鍵沖突問(wèn)題
- 詳解Java中synchronized關(guān)鍵字的死鎖和內(nèi)存占用問(wèn)題
- Oracle外鍵不加索引引起死鎖示例
- 使用鉤子如何鎖定鍵盤(pán)的方法分享
- Oracle 數(shù)據(jù)庫(kù)針對(duì)表主鍵列并發(fā)導(dǎo)致行級(jí)鎖簡(jiǎn)單演示
- Linux中使用VS Code編譯調(diào)試C++項(xiàng)目詳解
- 實(shí)戰(zhàn)開(kāi)發(fā)為單片機(jī)的按鍵加一個(gè)鎖防止多次觸發(fā)的細(xì)節(jié)
相關(guān)文章
SQL Server 監(jiān)控磁盤(pán)IO錯(cuò)誤,msdb.dbo.suspect_pages
suspect_pages 表位于 msdb 數(shù)據(jù)庫(kù)中,是在 SQL Server 2005 中引入的。用于維護(hù)有關(guān)可疑頁(yè)的信息的 suspect_pages2014-10-10
SQLSERVER ISNULL 函數(shù)與判斷值是否為空的sql語(yǔ)句
由于服務(wù)器設(shè)置不當(dāng)導(dǎo)致sqlserver的某個(gè)字段為空,導(dǎo)致部分內(nèi)容顯示失敗,所有這里需要將為空的字符替換為制定的字符2013-11-11
SQL SERVER使用REPLACE將某一列字段中的某個(gè)值替換為其他的值
本節(jié)主要介紹了SQL SERVER使用REPLACE將某一列字段中的某個(gè)值替換為其他的值,需要的朋友可以參考下2014-08-08
sqlserver中向表中插入多行數(shù)據(jù)的insert語(yǔ)句
關(guān)于sql 2000中如何使用insert語(yǔ)句插入多行記錄,可是郁悶壞了我。2010-08-08
SQL Server使用Windows身份驗(yàn)證與JDBC連接數(shù)據(jù)庫(kù)的操作流程
在企業(yè)級(jí)應(yīng)用中,數(shù)據(jù)庫(kù)的安全性是非常重要的,SQL Server 提供了多種身份驗(yàn)證方式,其中 Windows 身份驗(yàn)證是一種較為安全且方便的管理方式,本文將介紹如何在 Java 中使用 JDBC 連接 SQL Server 數(shù)據(jù)庫(kù),并且通過(guò) Windows 身份驗(yàn)證來(lái)確保數(shù)據(jù)訪問(wèn)的安全性2024-12-12
SQL中函數(shù) replace 的參數(shù)1的數(shù)據(jù)類(lèi)型ntext無(wú)效的解決方法
SQL中函數(shù) replace 的參數(shù) 1 的數(shù)據(jù)類(lèi)型 ntext 無(wú)效。找了半天找到了解決辦法2010-06-06

