mysql同一個事務中update,insert導致死鎖問題分析解決

neuyu發表於2021-09-09

現象:在一個repeatable read級別的事務中採用先update再insert的方式,當這段程式碼併發執行時造成死鎖;

示例如下: 如表student中只有一條記錄 ,該記錄的code 欄位值為1,且該表在code上建立索引。

transaction A:

update student set yn=1 where code = '2'; insert into student (code, …) values ('2', ...);

transaction B:

update student set yn=1 where code = '3'; insert into student (code, …) values ('3', ...);

此時A、B事務會出現死鎖現象。

原因:

在repeatable級別,update/select … for update/delete不存在的記錄時會hold一個X(互斥)gap鎖,當執行順序如下時:

  1. T-A update student set yn=1 where code = '2'; ------T-A獲得一個X的next-key鎖

  2. T-B update student set yn=1 where code = '3'; ------T-B獲得一個X的next-key鎖

  3. T-B insert into student (code, …) values ('3', ...); ------T-B需獲取一個insert intention gap lock,需等待T-A的next-key鎖釋放

  4. T-A insert into student (code, …) values ('2', ...); ------T-A同理,等待T-B的next-key鎖釋放死鎖產生

解決方案:

第一種方案:將事務隔離級別降低到read committed即可,此時無gap鎖,T-A、T-B無衝突。

第二種方案:事務隔離級別仍然為repeatable read,但將引數innodb_locks_unsafe_for_binlog置為true。

原文連結:

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4550/viewspace-2805610/,如需轉載,請註明出處,否則將追究法律責任。

相關文章