mysql先删后增并发时出现死锁_MySQL死锁案例分析一(先delete,再insert,导致死锁)...
一、死鎖案例
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)題。
- 上一篇: 语言程序设计第4版黄洪艺_谭浩强《C程序
- 下一篇: java与MySQL做购物系统_java