熟悉或者了解數據庫的朋友都知道鎖的概念,這里不做過多的解析!鎖的種類有很多,不同數據庫的鎖管理方式也不同。這里主要談下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
1begin;
2begin;
3select * from test where
a = 4 for update;
4select * from test where
a<=4 lock in share mode;
#等待
5insert 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引擎在這里主動選擇死鎖。