mysql先删后增并发时出现死锁_MySQL死锁案例分析一(先delete,再insert,导致死锁)...
一、死鎖案例
MySQL版本:Percona MySQL Server 5.7.19
隔離級別:可重復讀(RR)
業務邏輯:并發下按某個索引字段先delete記錄,再insert記錄
比如:begin;delete?from?tb?where?order_id?=?xxx;insert?into?tb(order_id)?values(xxx);
commit;
二、MySQL鎖基本概念
S:共享鎖(行級鎖)
X:排他鎖(行級鎖)
IS:意向共享鎖(表級鎖)
IX:意向排他鎖(表級鎖)
以上4種鎖的兼容性見下表:
鎖模式兼容性表gap鎖與gap鎖之間不沖突
rec insert intention(插入意向鎖)與gap鎖沖突。
三、模擬復現死鎖
打開參數,從innodb status獲取更多的鎖信息。
set GLOBAL innodb_status_output_locks=ON;
表結構:CREATE?TABLE?`tb`?(??`order_id`?int(11)?DEFAULT?NULL,
KEY?`idx_order_id`?(`order_id`)
)?ENGINE=InnoDB?DEFAULT?CHARSET=utf8
表中數據:mysql>?select?*?from?tb;
+----------+|?order_id?|+----------+|???????10?||???????20?|+----------+2?rows?in?set?(0.00?sec)
事務執行步驟: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;(死鎖)當session1執行delete from tb where order_id=15;,由于條件order_id=15的記錄不存在,session1 獲得2個鎖結構,分別是意向排他鎖IX(表級鎖)、gap鎖(行級鎖),如下:---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當session2執行delete from tb where order_id=15;,同樣由于order_id=15的記錄不存在,session2 也獲得2個鎖結構,分別是意向排他鎖IX(表級鎖)、gap鎖(行級鎖),如下:---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當session2執行insert into tb select 15;, session2 已經獲取到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當session1執行insert into tb select 15;,session1 已獲取到IX鎖,gap鎖, 等待rec insert intention(插入意向鎖), session1, session2 都在等待插入意向鎖, 插入意向鎖與gap鎖沖突,雙方都沒有釋放gap鎖,又都在等待插入意向鎖,死鎖發生。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)
四、案例擴展
以上死鎖案例,業務代碼邏輯是多線程并發下,有可能多個線程會執行相同order_id的job,比如兩個線程執行的order_id 都是15。
另外一種情況,多個線程間,不會執行到相同order_id的情況,也可能發生死鎖。比如一個線程order_id=15,另外一個線程order_id=16,如下所示:
事務執行步驟: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)
作者:偏執的工匠
鏈接:https://www.jianshu.com/p/f8495015dace
總結
以上是生活随笔為你收集整理的mysql先删后增并发时出现死锁_MySQL死锁案例分析一(先delete,再insert,导致死锁)...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 语言程序设计第4版黄洪艺_谭浩强《C程序
- 下一篇: 图片优化_网站里的图片应该如何优化