MySQL 死鎖產(chǎn)生原因及解決方法

死鎖報錯日志:

Deadlock found when trying to get lock; try restarting transaction

死鎖報錯示例:

1、各自鎖住對方進程正在使用的行數(shù)據(jù)
譬如先執(zhí)行:

-- session1
BEGIN;
UPDATE students SET memo='DLLock' WHERE dbid =9;
-- session2
BEGIN;
UPDATE students SET memo='DLLock' WHERE dbid =7;

再執(zhí)行:

-- session1
UPDATE students SET memo='DLLock' WHERE dbid =7;
-- session2
UPDATE students SET memo='DLLock' WHERE dbid =9;

再比如下面的情況:

-- session1
BEGIN;
UPDATE students SET memo='DLLock' WHERE dbid =9;
-- session2
BEGIN;
SELECT dbid FROM students WHERE dbid<20 for UPDATE;

執(zhí)行完以上后再在session1中執(zhí)行如下,即可產(chǎn)生死鎖:

UPDATE students SET memo='DdLock' WHERE dbid =1;

因為session2中的 dbid<20 會先對小于9的數(shù)據(jù)先加鎖(id-9已經(jīng)被session1提前加鎖),此時session1再對id-1的數(shù)據(jù)執(zhí)行加鎖,就會產(chǎn)生爭用,從而產(chǎn)生死鎖。

2、批量入庫,不存在則新增,存在則更新的情況:
假設(shè)目前 students 表中不存在 dbid 為 19 和 20 的數(shù)據(jù),此時需要新增

-- session1
BEGIN;
SELECT * FROM students WHERE dbid =19 for UPDATE;
-- session2
BEGIN;
SELECT * FROM students WHERE dbid =20 for UPDATE;

執(zhí)行完以上后再在各自的session中中執(zhí)行插入操作,即可產(chǎn)生死鎖:

-- session1
INSERT INTO `students` (`dbid`, `uid`, `uname`) VALUES (19, 39, '小明明');
-- session2
INSERT INTO `students` (`dbid`, `uid`, `uname`) VALUES (20, 35, '小紅紅');

為何兩條不存在的數(shù)據(jù)也會產(chǎn)生死鎖,是因為:

  • 當對已存在的行進行鎖定時(主鍵),mysql就只有行鎖。
  • 當對未存在的行進行鎖的時候(即使條件為主鍵),mysql會鎖住一段范圍(即gap鎖),其鎖范圍為:
    (無窮小或小于表中鎖住id的最大值,無窮大或大于表中鎖住id的最小值)

如果表中目前有已有的id為18,那么就鎖住 [19,無窮大);
如果表中目前已有的 id 區(qū)間為(11 , 30),那么就鎖住[12,29];
所以示例2中的兩個session其實鎖住的是相同 gap 中的數(shù)據(jù),因此執(zhí)行插入時才會產(chǎn)生 dead-lock;對于這種此類示例2的死鎖解決辦法是用mysql特有的語法 ON DUPLICATE KEY UPDATE來解決此問題;
該語法的意思為:

  • 在insert時候,如果insert的數(shù)據(jù)會引起唯一索引(包括主鍵索引)的沖突,即唯一值重復了,則不會執(zhí)行insert操作,而執(zhí)行后面的update操作。

如下兩條語句最終的執(zhí)行效果相同:

-- 1
INSERT INTO table (a,b,c) VALUES (1,2,3) ON DUPLICATE KEY UPDATE c=c+1;  
-- 2
UPDATE table SET c=c+1 WHERE a=1;

因為相對于主鍵來說,insert語句,插入的行不管是否存在,都只有行鎖。


就到這里吧!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容