標籤:mysql 死結
熟悉或者瞭解資料庫的朋友都知道鎖的概念,這裡不做過多的解析!鎖的種類有很多,不同資料庫的鎖管理方式也不同。這裡主要談下MySQL innodb引擎下的死結。
死結通俗的來講就是2個事務相互請求對方持有的鎖,這樣就會造成2個事務相互等待對方釋放的鎖資源,於是這就是死結。
| 事務A |
事務B |
begin;
|
|
| select * from t where a = 1 for update; |
begin; |
|
select * from t where a = 2 for update; |
select * from t where a = 2 for update; #等待 |
|
|
select * from t where a = 1 for update; #ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction |
首先INNODB引擎不會復原大多數的異常,但死結除外。再發現死結後,Innodb會立即復原其中一個事務(這裡復原依據,會設計到權重問題)。例子中事務B被復原!這是最常見的一種死結例子。
MySQL還有另外一種死結情況:當前事務持有待插入記錄的下一個記錄的X鎖(獨佔鎖定),但此時等待的隊列中存在一個S鎖的請求,則可能會發生死結。首先建立一個測試用的表,並插入資料:
create table test( a int primary key) engine=innodb;
insert into test values (1),(2),(4),(5);
| 時間 |
事務A |
事務B |
| 1 |
begin; |
|
| 2 |
|
begin; |
| 3 |
select * from test where a = 4 for update; |
|
| 4 |
|
select * from test where a<=4 lock in share mode; #等待 |
| 5 |
insert into test values (3) ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction |
|
| 6 |
|
#事務獲得鎖,正常運行 |
事務A中已經對記錄4持有了X鎖,但會話A插入記錄3的時候會導致死結發生。這個問題產生是由於事務B中請求記錄4的S鎖而發生等待,但之前請求鎖對於主鍵記錄1、2都已經成功,若再時間5能插入記錄,那麼事務B在擷取記錄4持有的S鎖後,還需要向後獲得記錄3的記錄,這顯得不合理。於是INNODB引擎在這裡主動選擇死結。
本文出自 “Jeff on the way” 部落格,請務必保留此出處http://nrain.blog.51cto.com/11930278/1895270
MySQL死結分析