MySQL error : Deadlock found when trying to get lock; try restarting transaction


在使用 MySQL 時,我們有時會遇到這樣的報錯:“Deadlock found when trying to get lock; try restarting transaction”。

14.5.5.3 How to Minimize and Handle Deadlocks 中有這樣一句話:

Deadlocks are not dangerous. Just try again.

死鎖不危險,重試一下就行。

實際上這個建議非常實用。

 

我們回顧一下死鎖發生的四個條件:

  1. 資源的獨占性(在某一時刻,最多只能被一個事務訪問);
  2. 請求與保持(事務獲取到鎖后,不會主動釋放);
  3. 不可剝奪(事務無法獲取另一個事務擁有的鎖);
  4. 循環等待(即事務 A 獲取到鎖 Lock1,等待 Lock2,同時事務 B 獲取到鎖 Lock2,等待 Lock1,此時,事務 A 和 B 循環等待對方釋放各自需要的鎖)。

值得注意的是,InnoDB 在絕大部分錯誤發生時都不會回滾(如:等待鎖超時不會回滾);

只有一個例外,那就是發生死鎖時,InnoDB 會回滾一個影響最小的事務(直接破壞了上面的第 3 點,這個事務就成為了 victim)。此時我們只要重試一下這個 victim 事務,那么,所有的事務都會成功提交。

 

同時,14.5.5.3 How to Minimize and Handle Deadlocks 中另一段話很重要:

InnoDB uses automatic row-level locking. You can get deadlocks even in the case of transactions that just insert or delete a single row. That is because these operations are not really atomic”; they automatically set locks on the (possibly several) index records of the row inserted or deleted.

insert / delete 一行也可能引發死鎖。

因為這些操作不是原子性的,它們在執行中會加 index record lock。

 

例子很好構造。

比如有一張表:create table t1 (id int PRIMARY KEY, name char(20) key);

有兩個 session 並發:

session 1:

insert into t1 (id, name) values(5, 'Branden');

session 2:

select * from t1 where name > ‘B’ and id >3;

session1 訪問 name>'B',會在 Ben、Bob上加 X 鎖,並且在 Alex 與 Ben、Ben 與 Bob、Bob 與 Cathy 間加 Gap lock,在聚簇索引 id 為 1、3上加X鎖;接下來要獲取聚簇索引上 id 為 6、7的 X 鎖,以及 (3, 6)、(6, 7)間的 gap lock。

session2 先獲取聚簇索引上(3, 6)間的 gap lock;接下來嘗試獲取 name 索引上(Ben, Bob)、(Bob, Cathy)間的 gap lock。

最后發生死鎖。

怎么消除呢?讓 select 中 where 子句先訪問 id ,再訪問 name。

可以閱讀這篇文章:http://hedengcheng.com/?p=771#_Toc374698321。

 

另外,有必要了解各種語句需要的鎖:14.5.3 Locks Set by Different SQL Statements in InnoDB

 

 

 

參考資料:

MySQL 5.7 Reference Manual:

14.5.2.3 Consistent Nonlocking Reads

14.5.2.4 Locking Reads

14.5.5 Deadlocks in InnoDB

 

Stack Overflow:

How to avoid mysql 'Deadlock found when trying to get lock; try restarting transaction'

Working around MySQL error “Deadlock found when trying to get lock; try restarting transaction”

 

理解innodb的鎖(record,gap,Next-Key lock)

MySQL InnoDB鎖機制之Gap Lock、Next-Key Lock、Record Lock解析

 


免責聲明!

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



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