高並發update的 死鎖產生原因


在說這個之前首先了解一下講一下update語句sql中的情況。

死鎖產生的條件:
出現循環等待資源。

update對鎖的流程:
       當sql發出一個update請求之后,數據庫會對表中的每條記錄加上U鎖。然后數據庫會根據where條件,將符合條件的記錄轉換為X鎖。對不滿足條件的記錄釋放U鎖。

環境模擬
1. 創建數據庫環境

--創建數據庫
  create database DeadLockTest;
--創建數據表 (沒有主鍵)
  use DealLocktest;
  create table t_table(
    A varchar(10),
    B varchar(10),
    C varchar(10)
  )
insert into  t_table values('a1','b1','c1');
insert into  t_table values('a2','b2','c2');
insert into  t_table values('a3','b3','c3');
insert into  t_table values('a4','b4','c4');
insert into  t_table values('a5','b5','c5');
insert into  t_table values('a6','b6','c6');
insert into  t_table values('a7','b7','c7');
insert into  t_table values('a8','b8','c8');
insert into  t_table values('a9','b9','c9');

創建完后,應該是這個樣子:
初始環境

2.准備高並發的查詢環境

因為一個人測試,很不好模擬現場的環境。所以使用sql 的waitfor 阻塞某一個查詢:
A要執行的sql語句:

 

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
 begin tran
    print convert(nvarchar(30),convert(datetime,getdate(),121),121)
       update t_table
     set A='a2'
     where B='b2'
    print convert(nvarchar(30),convert(datetime,getdate(),121),121)
    EXEC sp_lock @@spid

   waitfor  delay '00:00:05'

   update t_table
     set A='b4'
     where B='b4'
     EXEC sp_lock @@spid
    print convert(nvarchar(30),convert(datetime,getdate(),121),121)
 commit tran

 

B要進行的sql語句

SET TRANSACTION ISOLATION LEVEL Read UNCOMMITTED
    begin tran
  update t_table
    set A='a1'
    where B='b1'
    EXEC sp_lock @@spid
   commit tran

因為A中第一條查詢和第二天查詢有5s間隔,所以整個的執行過程為:
1、執行A的第一條語句 阻塞5s
2、執行B的查詢
3、A的阻塞釋放,要執行A的第二條語句

要執行的圖解:


分析:
1、執行A的查詢的時候,數據庫將所有的記錄加上U鎖,然后將將不是c2的記錄全部釋放U鎖。對滿足條件的數據添加X鎖。此時,A事務還沒有結束,A不會釋放此時的X鎖。
2、B查詢的時候,B會對表中的所有記錄添加U鎖,因為B查詢要用到t_table這張表,B查詢c1的時候,滿足條件給c1添加上X鎖。執行c=2的時候,要給c2加U鎖,此時該記錄被A添加了X鎖。所以B查詢需要等A釋放的X鎖,才可以執行。此時B等待。B要等待A釋放c2的X鎖
3、A的阻塞釋放之后,A要進行第二條查詢。這個時候A要對符合第二個查詢條件的記錄添加X鎖。當執行c1的時候,c1剛才被B添加了X鎖。所以此時A等待。A在等待B的U鎖釋放。
結論
A在等待B釋放X鎖,B在等待A釋放X鎖。所以才會發生死鎖。


解決方案:

給查詢條件加索引,原因參考下一篇詳解索引。

總結
死鎖的發生,肯定是因為資源的循環等待。分析死鎖,就是分析這些進程分別需要等待什么資源。在sql server中 一般可以使用 sql profiler進行死鎖的監控。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM