innodb死鎖1213 - Deadlock found when trying to get lock; try restarting transaction


問題背景:外網mysql在執行玩家保存數據的存儲過程時,出現死鎖 Deadlock found when trying to get lock; try restarting transaction

產生原因:兩個線程AB提交事務時,對同一張表 test_deadlock(表名為化名)進行了如下操作:

  A線程根據表主鍵進行插入更新(insert into ON DUPLICATE KEY UPDATE ),此時為行鎖,

  B線程對表進行刪除部分數據(並不是根據主鍵),此時為表鎖,

  A線程對表進行刪除部分數據(並不是根據主鍵),此時為表鎖。此刻,B線程錯誤提示死鎖。

重現過程

CREATE TABLE `test_deadlock` (
  `a` int(11) NOT NULL,
  `b` int(11) NOT NULL,
  `c` int(11) NOT NULL,
  PRIMARY KEY (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into `test_deadlock`(a,b,c) values(4,4,4) ON DUPLICATE KEY UPDATE b=4,c=4;
insert into `test_deadlock`(a,b,c) values(3,3,3) ON DUPLICATE KEY UPDATE b=3,c=3;
insert into `test_deadlock`(a,b,c) values(2,2,2) ON DUPLICATE KEY UPDATE b=2,c=2;
insert into `test_deadlock`(a,b,c) values(1,1,1) ON DUPLICATE KEY UPDATE b=1,c=1;

用Navicate 工具,打開AB兩個窗口,

A窗口執行:

  start TRANSACTION;

  insert into `test_deadlock`(a,b,c) values(1,1,1) ON DUPLICATE KEY UPDATE b=1,c=1;

B窗口執行:

  update test_deadlock set b = 2 where b = 2;

A窗口執行:

  update test_deadlock set b = 4 where b = 4; 此刻B窗口提示死鎖。

以上想重復實驗,請在A窗口執行:commit;

如何避免死鎖

  1.使用事務,但是避免使用長事務,將大事務拆小,分段多提交。

  2.sql語句條件是主鍵或者索引,這樣執行后為行鎖,避免表鎖,從而避免死鎖。


免責聲明!

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



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