亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

MySQL?insert死鎖問(wèn)題解決詳細(xì)記錄

 更新時(shí)間:2022年11月04日 12:01:58   作者:jhgdike  
上周遇到一個(gè)因insert而引發(fā)的死鎖問(wèn)題,其成因比較令人費(fèi)解,下面這篇文章主要給大家介紹了關(guān)于MySQL?insert死鎖問(wèn)題解決詳細(xì)記錄的相關(guān)資料,需要的朋友可以參考下

Insert死鎖問(wèn)題剖析

線(xiàn)上有個(gè)批量的insert … on duplicate key update語(yǔ)句引發(fā)的死鎖問(wèn)題,查過(guò)很多資料并且親自嘗試過(guò)后,發(fā)現(xiàn)好多博客說(shuō)的都是錯(cuò)的,其實(shí)本身只跟insert的順序有關(guān),在此記錄一下備忘。

前置知識(shí)

X型鎖:排他鎖

S型鎖:共享鎖

行鎖:鎖住一行記錄

Next-Key鎖:左開(kāi)右閉區(qū)間

Gap鎖:左右開(kāi)區(qū)間

構(gòu)造死鎖

建表:

CREATE TABLE hero (
    number INT AUTO_INCREMENT,
    name VARCHAR(100),
    country varchar(100),
    PRIMARY KEY (number),
    UNIQUE KEY uk_name (name)
) Engine=InnoDB CHARSET=utf8;

構(gòu)造初始數(shù)據(jù):

INSERT INTO hero VALUES
    (1, 'l劉備', '蜀'),
    (3, 'z諸葛亮', '蜀'),
    (8, 'c曹操', '魏'),
    (15, 'x荀彧', '魏'),
    (20, 's孫權(quán)', '吳');

好了,開(kāi)始了,下面開(kāi)始兩個(gè)事務(wù),按順序執(zhí)行:

事務(wù)1

begin:
INSERT INTO hero(name, country) VALUES('g關(guān)羽', '蜀');

事務(wù)2

begin:
INSERT INTO hero(name, country) VALUES('g關(guān)羽', '蜀');

事務(wù)1

INSERT INTO hero(name, country) VALUES('d鄧艾', '魏');

來(lái)了,它來(lái)了,這個(gè)時(shí)候我們就可以注意到事務(wù)2的死鎖報(bào)錯(cuò)了:

# 事務(wù)T2
mysql> INSERT INTO hero(name, country) VALUES('g關(guān)羽', '蜀');
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

原因

請(qǐng)?zhí)砑訄D片描述

  • T1先插入name值為g關(guān)羽的記錄,可以插入成功,此時(shí)對(duì)應(yīng)的唯一索引記錄被隱式鎖保護(hù)
  • T2隨后插入name值為g關(guān)羽的記錄(必須為同一條記錄),發(fā)生阻塞,并且T2會(huì)想要獲取一把S型next-key鎖(只有唯一索引才會(huì)發(fā)生)(左開(kāi)右閉)。此時(shí)T1的隱式鎖轉(zhuǎn)化為顯示鎖(X型行鎖)
  • T1想要插入d鄧艾的記錄,由于T2的next-key鎖(雖然沒(méi)被T2持有,但鎖已存在)而進(jìn)入阻塞等待狀態(tài),進(jìn)而發(fā)生死鎖

故死鎖產(chǎn)生的原因

  • T1在等待T2釋放name值為’g關(guān)羽’的二級(jí)索引記錄上的gap鎖。
  • T2在等待T1釋放name值為’g關(guān)羽’的二級(jí)索引記錄上的X型行鎖。

MySQL 5.7 的死鎖

前提

在比較新的版本中都可以遇見(jiàn)的,只要是insert … on duplicate key update 觸發(fā)了后面的update操作,那么此時(shí)其他的insert語(yǔ)句都會(huì)被阻塞,這主要是為了解決RR下的一些幻讀問(wèn)題。

示例

在5.7版本中又有一些特殊情況。還是舉例

假如有如下表和數(shù)據(jù)

demo表

idnamevalue
11112
12222
13332

此時(shí),如果事務(wù)1執(zhí)行了:

insert into demo (name, value) VALUES ("333", 1) ON duplicate KEY UPDATE value = value + 1;

事務(wù)2執(zhí)行了:

insert into demo (name, value) VALUES ("223", 1) ON duplicate KEY UPDATE value = value + 1;

事務(wù)3執(zhí)行了:

insert into demo (name, value) VALUES ("224", 1) ON duplicate KEY UPDATE value = value + 1;

那么首先事務(wù)2和事務(wù)3會(huì)被阻塞,然后事務(wù)1提交了,事務(wù)2和事務(wù)3就會(huì)發(fā)生死鎖,其中一個(gè)爆出死鎖的錯(cuò)誤然后失敗,另一個(gè)則成功執(zhí)行。

原因

當(dāng)insert … on duplicate key 執(zhí)行成功之時(shí),會(huì)在當(dāng)前唯一鍵和之前唯一鍵之間加一個(gè)隱式GAP鎖,如上會(huì)在222和333之間加上GAP鎖,此時(shí),事務(wù)2和事務(wù)3想插入新數(shù)據(jù)都會(huì)被GAP鎖阻塞,此時(shí)GAP鎖轉(zhuǎn)為顯式,事務(wù)2和事務(wù)3同時(shí)也分別想要獲取X型的插入意向鎖。

然后事務(wù)1提交,此時(shí)GAP鎖并不會(huì)被釋放,由于5.7的bug,事務(wù)2和事務(wù)3都會(huì)拿到GAP鎖,此時(shí)他們?nèi)カ@取插入意向鎖的時(shí)候由于GAP鎖被對(duì)方拿到而矛盾,進(jìn)而死鎖。

解決方案

網(wǎng)上有很多方法,這里我提出一個(gè)另類(lèi)的想法。

我們可以先用非事務(wù)的insert ignore去初始化數(shù)據(jù),后面在用事務(wù)的update操作去更新。

參考:https://zhuanlan.zhihu.com/p/457191971

總結(jié)

到此這篇關(guān)于MySQL insert死鎖問(wèn)題的文章就介紹到這了,更多相關(guān)MySQL insert死鎖問(wèn)題內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • MYSQL Left Join優(yōu)化(10秒優(yōu)化到20毫秒內(nèi))

    MYSQL Left Join優(yōu)化(10秒優(yōu)化到20毫秒內(nèi))

    在實(shí)際開(kāi)發(fā)中,相信大多數(shù)人都會(huì)用到j(luò)oin進(jìn)行連表查詢(xún),但是有些人發(fā)現(xiàn),用join好像效率很低,而且驅(qū)動(dòng)表不同,執(zhí)行時(shí)間也不同。那么join到底是如何執(zhí)行的呢,本文就詳細(xì)的介紹一下
    2021-12-12
  • Mysql 5.6.24安裝實(shí)例教程

    Mysql 5.6.24安裝實(shí)例教程

    這篇文章主要介紹了Mysql 5.6.24安裝實(shí)例教程,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-12-12
  • mysql?sock文件存儲(chǔ)了什么信息

    mysql?sock文件存儲(chǔ)了什么信息

    這篇文章主要為大家介紹了mysql?sock文件存儲(chǔ)了什么信息的內(nèi)容詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • mysql運(yùn)行net start mysql報(bào)服務(wù)名無(wú)效的解決辦法

    mysql運(yùn)行net start mysql報(bào)服務(wù)名無(wú)效的解決辦法

    這篇文章主要為大家詳細(xì)介紹了mysql運(yùn)行net start mysql報(bào)服務(wù)名無(wú)效的解決辦法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-01-01
  • mysql中多表刪除其中ID相同記錄的方法

    mysql中多表刪除其中ID相同記錄的方法

    這篇文章主要介紹了mysql中多表刪除其中ID相同記錄的方法,需要的朋友可以參考下
    2014-04-04
  • MySQL?賬號(hào)密碼錯(cuò)誤終極解決方法

    MySQL?賬號(hào)密碼錯(cuò)誤終極解決方法

    這篇文章主要介紹了MySQL?賬號(hào)密碼錯(cuò)誤終極解決方法,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-08-08
  • 詳解MySQL中UNION的用法

    詳解MySQL中UNION的用法

    這篇文章主要介紹了詳解MySQL中UNION的用法,是MySQL入門(mén)學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-05-05
  • MySQL數(shù)據(jù)庫(kù)操作DQL正則表達(dá)式

    MySQL數(shù)據(jù)庫(kù)操作DQL正則表達(dá)式

    這篇文章主要介紹了MySQL數(shù)據(jù)庫(kù)操作DQL正則表達(dá)式,正則表達(dá)式描述了一種字符串匹配的規(guī)則,正則表達(dá)式本身就是一個(gè)字符串,使用這個(gè)字符串來(lái)描述、用來(lái)定義匹配規(guī)則,匹配一系列符合某個(gè)句法規(guī)則的字符串
    2022-07-07
  • mysql enum字段類(lèi)型的謹(jǐn)慎使用

    mysql enum字段類(lèi)型的謹(jǐn)慎使用

    本文主要介紹了mysql enum字段類(lèi)型使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07
  • Mysql的Explain使用方式及索引總結(jié)

    Mysql的Explain使用方式及索引總結(jié)

    這篇文章主要介紹了Mysql的Explain使用方式及索引總結(jié),具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-12-12

最新評(píng)論