日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > 数据库 >内容正文

数据库

mysql先删后增并发时出现死锁_MySQL死锁案例分析一(先delete,再insert,导致死锁)...

發(fā)布時(shí)間:2024/7/23 数据库 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mysql先删后增并发时出现死锁_MySQL死锁案例分析一(先delete,再insert,导致死锁)... 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、死鎖案例

MySQL版本:Percona MySQL Server 5.7.19

隔離級(jí)別:可重復(fù)讀(RR)

業(yè)務(wù)邏輯:并發(fā)下按某個(gè)索引字段先delete記錄,再insert記錄

比如:begin;delete?from?tb?where?order_id?=?xxx;insert?into?tb(order_id)?values(xxx);

commit;

二、MySQL鎖基本概念

S:共享鎖(行級(jí)鎖)

X:排他鎖(行級(jí)鎖)

IS:意向共享鎖(表級(jí)鎖)

IX:意向排他鎖(表級(jí)鎖)

以上4種鎖的兼容性見(jiàn)下表:

鎖模式兼容性表gap鎖與gap鎖之間不沖突

rec insert intention(插入意向鎖)與gap鎖沖突。

三、模擬復(fù)現(xiàn)死鎖

打開(kāi)參數(shù),從innodb status獲取更多的鎖信息。

set GLOBAL innodb_status_output_locks=ON;

表結(jié)構(gòu):CREATE?TABLE?`tb`?(??`order_id`?int(11)?DEFAULT?NULL,

KEY?`idx_order_id`?(`order_id`)

)?ENGINE=InnoDB?DEFAULT?CHARSET=utf8

表中數(shù)據(jù):mysql>?select?*?from?tb;

+----------+|?order_id?|+----------+|???????10?||???????20?|+----------+2?rows?in?set?(0.00?sec)

事務(wù)執(zhí)行步驟:session1session2begin

begin

delete from tb where order_id=15;

delete from tb where order_id=15;

insert into tb select 15;(等待鎖)

insert into tb select 15;(死鎖)當(dāng)session1執(zhí)行delete from tb where order_id=15;,由于條件order_id=15的記錄不存在,session1 獲得2個(gè)鎖結(jié)構(gòu),分別是意向排他鎖IX(表級(jí)鎖)、gap鎖(行級(jí)鎖),如下:---TRANSACTION?1055191443,?ACTIVE?20?sec2?lock?struct(s),?heap?size?1136,?1?row?lock(s)

MySQL?thread?id?315642,?OS?thread?handle?139960342456064,?query?id?150462030?localhost?root

TABLE?LOCK?table?`db`.`tb`?trx?id?1055191443?lock?mode?IX

RECORD?LOCKS?space?id?1337?page?no?4?n?bits?72?index?idx_order_id?of?table?`db`.`tb`?trx?id?1055191443?lock_mode?X?locks?gap?before?rec當(dāng)session2執(zhí)行delete from tb where order_id=15;,同樣由于order_id=15的記錄不存在,session2 也獲得2個(gè)鎖結(jié)構(gòu),分別是意向排他鎖IX(表級(jí)鎖)、gap鎖(行級(jí)鎖),如下:---TRANSACTION?1055191444,?ACTIVE?3?sec2?lock?struct(s),?heap?size?1136,?1?row?lock(s)

MySQL?thread?id?315336,?OS?thread?handle?139960562685696,?query?id?150462412?localhost?root

TABLE?LOCK?table?`db`.`tb`?trx?id?1055191444?lock?mode?IX

RECORD?LOCKS?space?id?1337?page?no?4?n?bits?72?index?idx_order_id?of?table?`db`.`tb`?trx?id?1055191444?lock_mode?X?locks?gap?before?rec當(dāng)session2執(zhí)行insert into tb select 15;, session2 已經(jīng)獲取到IX鎖,gap鎖,等待 rec insert intention(插入意向鎖)---TRANSACTION?1055191444,?ACTIVE?68?sec?inserting

mysql?tables?in?use?1,?locked?1LOCK?WAIT?3?lock?struct(s),?heap?size?1136,?2?row?lock(s),?undo?log?entries?1MySQL?thread?id?315336,?OS?thread?handle?139960562685696,?query?id?150462778?localhost?root?executing

insert?into?tb?select?15-------?TRX?HAS?BEEN?WAITING?2?SEC?FOR?THIS?LOCK?TO?BE?GRANTED:

RECORD?LOCKS?space?id?1337?page?no?4?n?bits?72?index?idx_order_id?of?table?`db`.`tb`?trx?id?1055191444?lock_mode?X?locks?gap?before?rec?insert?intention?waiting

------------------

TABLE?LOCK?table?`db`.`tb`?trx?id?1055191444?lock?mode?IX

RECORD?LOCKS?space?id?1337?page?no?4?n?bits?72?index?idx_order_id?of?table?`db`.`tb`?trx?id?1055191444?lock_mode?X?locks?gap?before?rec

RECORD?LOCKS?space?id?1337?page?no?4?n?bits?72?index?idx_order_id?of?table?`db`.`tb`?trx?id?1055191444?lock_mode?X?locks?gap?before?rec?insert?intention?waiting當(dāng)session1執(zhí)行insert into tb select 15;,session1 已獲取到IX鎖,gap鎖, 等待rec insert intention(插入意向鎖), session1, session2 都在等待插入意向鎖, 插入意向鎖與gap鎖沖突,雙方都沒(méi)有釋放gap鎖,又都在等待插入意向鎖,死鎖發(fā)生。LATEST?DETECTED?DEADLOCK

------------------------2018-11-03?17:15:11?0x7f4b0e7ea700***?(1)?TRANSACTION:

TRANSACTION?1055191444,?ACTIVE?135?sec?inserting

mysql?tables?in?use?1,?locked?1LOCK?WAIT?3?lock?struct(s),?heap?size?1136,?2?row?lock(s),?undo?log?entries?1MySQL?thread?id?315336,?OS?thread?handle?139960562685696,?query?id?150462778?localhost?root?executing

insert?into?tb?select?15***?(1)?WAITING?FOR?THIS?LOCK?TO?BE?GRANTED:

RECORD?LOCKS?space?id?1337?page?no?4?n?bits?72?index?idx_order_id?of?table?`db`.`tb`?trx?id?1055191444?lock_mode?X?locks?gap?before?rec?insert?intention?waiting

***?(2)?TRANSACTION:

TRANSACTION?1055191443,?ACTIVE?201?sec?inserting,?thread?declared?inside?InnoDB?5000mysql?tables?in?use?1,?locked?13?lock?struct(s),?heap?size?1136,?2?row?lock(s),?undo?log?entries?1MySQL?thread?id?315642,?OS?thread?handle?139960342456064,?query?id?150463172?localhost?root?executing

insert?into?tb?select?15***?(2)?HOLDS?THE?LOCK(S):

RECORD?LOCKS?space?id?1337?page?no?4?n?bits?72?index?idx_order_id?of?table?`db`.`tb`?trx?id?1055191443?lock_mode?X?locks?gap?before?rec

***?(2)?WAITING?FOR?THIS?LOCK?TO?BE?GRANTED:

RECORD?LOCKS?space?id?1337?page?no?4?n?bits?72?index?idx_order_id?of?table?`db`.`tb`?trx?id?1055191443?lock_mode?X?locks?gap?before?rec?insert?intention?waiting

***?WE?ROLL?BACK?TRANSACTION?(2)

四、案例擴(kuò)展

以上死鎖案例,業(yè)務(wù)代碼邏輯是多線程并發(fā)下,有可能多個(gè)線程會(huì)執(zhí)行相同order_id的job,比如兩個(gè)線程執(zhí)行的order_id 都是15。

另外一種情況,多個(gè)線程間,不會(huì)執(zhí)行到相同order_id的情況,也可能發(fā)生死鎖。比如一個(gè)線程order_id=15,另外一個(gè)線程order_id=16,如下所示:

事務(wù)執(zhí)行步驟:session1session2begin

begin

delete from tb where order_id=15;

delete from tb where order_id=16;

insert into tb select 16;(等待鎖)

insert into tb select 15;(死鎖)

鎖情況與上述相同,不再贅述,死鎖信息如下:LATEST?DETECTED?DEADLOCK

------------------------2018-11-03?17:28:30?0x7f4b0e667700***?(1)?TRANSACTION:

TRANSACTION?1055191450,?ACTIVE?18?sec?inserting

mysql?tables?in?use?1,?locked?1LOCK?WAIT?3?lock?struct(s),?heap?size?1136,?2?row?lock(s),?undo?log?entries?1MySQL?thread?id?316221,?OS?thread?handle?139960338228992,?query?id?150467652?localhost?root?executing

insert?into?tb?select?16***?(1)?WAITING?FOR?THIS?LOCK?TO?BE?GRANTED:

RECORD?LOCKS?space?id?1337?page?no?4?n?bits?72?index?idx_order_id?of?table?`db`.`tb`?trx?id?1055191450?lock_mode?X?locks?gap?before?rec?insert?intention?waiting

***?(2)?TRANSACTION:

TRANSACTION?1055191449,?ACTIVE?28?sec?inserting,?thread?declared?inside?InnoDB?5000mysql?tables?in?use?1,?locked?13?lock?struct(s),?heap?size?1136,?2?row?lock(s),?undo?log?entries?1MySQL?thread?id?316222,?OS?thread?handle?139960340870912,?query?id?150467681?localhost?root?executing

insert?into?tb?select?15***?(2)?HOLDS?THE?LOCK(S):

RECORD?LOCKS?space?id?1337?page?no?4?n?bits?72?index?idx_order_id?of?table?`db`.`tb`?trx?id?1055191449?lock_mode?X?locks?gap?before?rec

***?(2)?WAITING?FOR?THIS?LOCK?TO?BE?GRANTED:

RECORD?LOCKS?space?id?1337?page?no?4?n?bits?72?index?idx_order_id?of?table?`db`.`tb`?trx?id?1055191449?lock_mode?X?locks?gap?before?rec?insert?intention?waiting

***?WE?ROLL?BACK?TRANSACTION?(2)

作者:偏執(zhí)的工匠

鏈接:https://www.jianshu.com/p/f8495015dace

總結(jié)

以上是生活随笔為你收集整理的mysql先删后增并发时出现死锁_MySQL死锁案例分析一(先delete,再insert,导致死锁)...的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。