【Mysql】兩條insert 語句產生的死鎖
背景:檢視status日誌發現兩條insert 出現了死鎖
注意:在innodb 日誌中如果提示 lock mode S /lock mode X ,其實都是gap鎖,如果是行記錄鎖 會提示but not gap ,請讀者朋友們在自己分析死鎖日誌的時候注意。
2.
可以確定,這個x鎖不是由於INSERT產生的,因為 INSERT可能產生的鎖包括檢查dup key時的s鎖,隱式鎖轉換為顯式鎖(not gap,要在二級索引上產生lock_mode為X的LOCK_ORDINARY型別的鎖(包括記錄及記錄前面的gap),據我所知一般是根據二級索引掃描進行記錄更新導致的。
3. 根據
LOCK WAIT 14 lock struct(s), heap size 2936, 7 row lock(s), undo log entries 7
有7個undo entires,而單純的INSERT一條記錄只有一個undo entry,因此可以推斷除了INSERT,必然還有別的操作
基於以上,事務除了INSERT,可能還存在DELETE/UPDATE,並且這些操作是走的二級索引來查詢更新記錄。
參考:
http://blog.itpub.net/22664653/viewspace-2145068/ ----楊奇龍
---insert ..select 語句產生死鎖
http://blog.itpub.net/7728585/viewspace-2146183/ ---insert ..select 語句產生死鎖--八怪
-
------------------------
-
LATEST DETECTED DEADLOCK
-
------------------------
-
2017-10-24 12:53:56 7f8fbc165700
-
*** (1) TRANSACTION:
-
TRANSACTION 596252578, ACTIVE 0 sec inserting
-
mysql tables in use 1, locked 1
-
LOCK WAIT 14 lock struct(s), heap size 2936, 7 row lock(s), undo log entries 7
-
MySQL thread id 17066316, OS thread handle 0x7f8eef3cf700, query id 2080508355 192.168.1.13 userservice update
-
insert into
-
svc_order_service_item
-
( work_order_id,
-
quantity
-
)
-
values ( 2373314,1
-
)
-
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
-
RECORD LOCKS space id 388 page no 27032 n bits 616 index `idx_svcorderserviceitem_workorderid_quantity` of table `ecejservice`.`svc_order_service_item` trx id 596252578 lock_mode X insert intention waiting
-
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
-
0: len 8; hex 73757072656d756d; asc supremum;;
-
-
*** (2) TRANSACTION:
-
TRANSACTION 596252580, ACTIVE 0 sec inserting
-
mysql tables in use 1, locked 1
-
15 lock struct(s), heap size 2936, 7 row lock(s), undo log entries 8
-
MySQL thread id 17061883, OS thread handle 0x7f8fbc165700, query id 2080508367 192.168.1.12 userservice update
-
insert into
-
-
svc_order_service_item
-
-
( work_order_id,
-
quantity,
-
)
-
values ( 2373315,
-
1
-
-
)
-
*** (2) HOLDS THE LOCK(S): --持有一個讀鎖
-
RECORD LOCKS space id 388 page no 27032 n bits 616 index `idx_svcorderserviceitem_workorderid_quantity` of table `ecejservice`.`svc_order_service_item` trx id 596252580 lock_mode X
-
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
-
0: len 8; hex 73757072656d756d; asc supremum;;
-
-
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
-
RECORD LOCKS space id 388 page no 27032 n bits 616 index `idx_svcorderserviceitem_workorderid_quantity` of table `ecejservice`.`svc_order_service_item` trx id 596252580 lock_mode X insert intention waiting
-
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
-
0: len 8; hex 73757072656d756d; asc supremum;;
-
-
*** WE ROLL BACK TRANSACTION (1)
- ------------
分析:
1.表上有聚集索引和二級索引,死鎖發生在二級索引idx_svcorderserviceitem_workorderid_quantity上2.
- RECORD LOCKS space id 388 page no 27032 n bits 616 index `idx_svcorderserviceitem_workorderid_quantity` of table `ecejservice`.`svc_order_service_item` trx id 596252578 lock_mode X insert intention waiting
3. 根據
LOCK WAIT 14 lock struct(s), heap size 2936, 7 row lock(s), undo log entries 7
有7個undo entires,而單純的INSERT一條記錄只有一個undo entry,因此可以推斷除了INSERT,必然還有別的操作
基於以上,事務除了INSERT,可能還存在DELETE/UPDATE,並且這些操作是走的二級索引來查詢更新記錄。
一個簡單但不完全相同的重現步驟:
DROP TABLE t1;
CREATE TABLE `t1` (
`a` int(11) NOT NULL AUTO_INCREMENT,
`b` int(11) DEFAULT NULL,
`c` int(11) DEFAULT NULL,
PRIMARY KEY (`a`),
KEY `b` (`b`)
) ENGINE=InnoDB ;
insert into t1(a, b,c) values(1,2,3),(5,4,6),(8, 7,9),(12,12,19),(15,15,11);
session1:
begin;
delete from t1 where b = 12;
//二級索引上lock_mode X、lock_mode X locks gap before rec以及主鍵上的lock_mode X locks rec but not gap
二級索引:heap_no=5, type_mode=3 (12上的LOCK_ORDINARY型別鎖,包括記錄和記錄前的GAP)
聚集索引:heap_no=5,type_mode=1027
二級索引:heap_no=6,type_mode=547(15上的GAP鎖)
session2:
begin;
delete from t1 where b = 7;
//二級索引上lock_mode X、lock_mode X locks gap before rec以及主鍵上的lock_mode X locks rec but not gap
二級索引:heap_no=4,type_mode=3 (7上的LOCK_ORDINARY型別鎖,包括記錄和記錄前的GAP)
聚集索引:heap_no=4,type_mode=1027
二級索引:heap_no=5,type_mode=547 (記錄12上的GAP鎖)
session1:
insert into t1 values (NULL, 6,10);
//新插入記錄聚集索引無衝突插入成功,二級索引等待插入意向鎖(lock_mode X locks gap before rec insert intention waiting)
二級索引,heap_no=4, type_mode=2819 (請求記錄7上面的插入意向鎖LOCK_X | LOCK_GAP | LOCK_INSERT_INTENTION, 需要等待session2
session2:
insert into t1 values (NULL, 7,10);
二級索引:heap_no=5, type_mode=2819 (請求記錄12上的插入意向鎖LOCK_X | LOCK_GAP | LOCK_INSERT_INTENTION,需要等待session1)
互相等待,導致發生死鎖
從列印的死鎖資訊來看,基本和線上發生的死鎖現象是一致的。
再舉一個例子
檢視死鎖日誌:
死鎖日誌是不是和上面的一樣?
再舉一個例子
-
-
mysql> select * from test01;
-
+----+-----+
-
| id | app |
-
+----+-----+
-
| 1 | 01 |
-
| 2 | 02 |
-
| 5 | 03 |
-
| 10 | 03 |
-
| 6 | 04 |
-
| 7 | 05 |
-
| 8 | 06 |
-
| 9 | 06 |
-
| 11 | 06 |
-
| 12 | 07 |
-
| 13 | 08 |
-
| 14 | 09 |
-
| 15 | 09 |
-
+----+-----+
- 13 rows in set (0.00 sec)
-
mysql> select * from test01;
- session1:
-
mysql> select now();start TRANSACTION;
-
+---------------------+
-
| now() |
-
+---------------------+
-
| 2018-01-25 16:08:46 |
-
+---------------------+
-
1 row in set (0.00 sec)
-
-
Query OK, 0 rows affected (0.00 sec)
-
-
mysql> select * from test01 where app='05' for update; ---第1步 鎖住【6.04】-【7.05】以及【7.05】-【8.06】 兩段區間
-
+----+-----+
-
| id | app |
-
+----+-----+
-
| 7 | 05 |
-
+----+-----+
-
1 row in set (0.00 sec)
-
-
mysql> insert into test01(app) values ('07'); --第三步 等待第二步釋放
-
Query OK, 1 row affected (23.24 sec)
-
-
-
-
session2:
-
mysql> select * from test01 where app='08' for update; --第二步 鎖住【12,07】-【13,08】以及【13,08】-【14,09】兩段區間
-
+----+-----+
-
| id | app |
-
+----+-----+
-
| 13 | 08 |
-
+----+-----+
-
1 row in set (0.00 sec)
-
-
mysql> insert into test01(app) values ('04'); ----第四步 等待第一步釋放,,於是死鎖
- ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction
檢視死鎖日誌:
-
LATEST DETECTED DEADLOCK
-
------------------------
-
2018-01-25 16:09:54 0x7f07d23ff700
-
*** (1) TRANSACTION:
-
TRANSACTION 5375, ACTIVE 51 sec inserting
-
mysql tables in use 1, locked 1
-
LOCK WAIT 5 lock struct(s), heap size 1136, 4 row lock(s), undo log entries 1
-
MySQL thread id 2294, OS thread handle 139671567841024, query id 42463 localhost root update
-
insert into test01(app) values ('07')
-
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
-
RECORD LOCKS space id 64 page no 4 n bits 80 index idx_app of table `devops`.`test01` trx id 5375 lock_mode X locks gap before rec insert intention waiting
-
Record lock, heap no 12 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
-
0: len 2; hex 3038; asc 08;;
-
1: len 4; hex 0000000d; asc ;;
-
-
*** (2) TRANSACTION:
-
TRANSACTION 5376, ACTIVE 38 sec inserting
-
mysql tables in use 1, locked 1
-
5 lock struct(s), heap size 1136, 4 row lock(s), undo log entries 1
-
MySQL thread id 2293, OS thread handle 139671568905984, query id 42464 localhost root update
-
insert into test01(app) values ('04')
-
*** (2) HOLDS THE LOCK(S):
-
RECORD LOCKS space id 64 page no 4 n bits 80 index idx_app of table `devops`.`test01` trx id 5376 lock_mode X
-
Record lock, heap no 12 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
-
0: len 2; hex 3038; asc 08;;
-
1: len 4; hex 0000000d; asc ;;
-
-
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
-
RECORD LOCKS space id 64 page no 4 n bits 80 index idx_app of table `devops`.`test01` trx id 5376 lock_mode X locks gap before rec insert intention waiting
-
Record lock, heap no 6 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
-
0: len 2; hex 3035; asc 05;;
-
1: len 4; hex 00000007; asc ;;
-
-
*** WE ROLL BACK TRANSACTION (2)
- ------------
死鎖日誌是不是和上面的一樣?
參考:
http://blog.itpub.net/22664653/viewspace-2145068/ ----楊奇龍
---insert ..select 語句產生死鎖
http://blog.itpub.net/7728585/viewspace-2146183/ ---insert ..select 語句產生死鎖--八怪
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29096438/viewspace-2146310/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 【Mysql】兩條select for update引起的死鎖MySql
- MySQL insert on duplicate key update 死鎖MySql
- Mysql 兩階段鎖和死鎖MySql
- 作業系統(5) 死鎖的概念 死鎖產生的必要條件 死鎖的處理策略 預防死鎖 避免死鎖 死鎖的檢測和解除 銀行家演算法作業系統演算法
- oracle 檢視死鎖語句Oracle
- 【Oracle】死鎖的產生與處理Oracle
- PostgreSQL模擬兩個update語句死鎖-利用掃描方法SQL
- MYSQL RC模式insert update 可能死鎖的情況MySql模式
- MySQL INSERT IGNORE語句的使用MySql
- 一條簡單的更新語句,MySQL是如何加鎖的?MySql
- MySQL死鎖案例分析一(先delete,再insert,導致死鎖)MySqldelete
- 非IMU模式下一條update語句產生REDO RECORD條數的探究模式
- Oracle:select 或 inactive 會話語句產生鎖?Oracle會話
- SQLSERVER 語句交錯引發的死鎖研究SQLServer
- 鎖的種類,阻塞,死鎖產生與解決辦法。
- Oracle 使用一條insert語句完成多表插入Oracle
- 【SQL】使用一條INSERT語句完成多表插入SQL
- ORA-00060死鎖的產生及解決
- MySQL:一個簡單insert語句的大概流程MySql
- 一條insert語句導致的效能問題分析(二)
- 一條insert語句導致的效能問題分析(一)
- SQLite Insert 語句SQLite
- 原來一條select語句在MySQL是這樣執行的《死磕MySQL系列 一》MySql
- mysql insert語句錯誤問題解決MySql
- MySQL 5.5 INSERT ... ON DUPLICATE KEY UPDATE語句說明MySql
- INSERT...SELECT語句對查詢的表加鎖嗎
- synchronized 內部原理、常見鎖策略、CAS、 以及死鎖的產生和解決synchronized
- sybase空間監控和死鎖檢測語句
- MySQL 死鎖和鎖等待MySql
- 查詢處理死鎖會話的sql語句(轉貼)會話SQL
- mysql innodb的行鎖(6) --不安全語句加鎖MySql
- mysql快速新增百萬條記錄的語句MySql
- 故障分析 | 從 Insert 併發死鎖分析 Insert 加鎖原始碼邏輯原始碼
- 用一條mysql語句插入多條資料MySql
- SQLite中特殊的INSERT語句SQLite
- 兩個看似奇怪的MySQL語句問題MySql
- 死鎖: delete+insert不存在PKdelete
- 如何透過sid查詢造成死鎖的sql語句,並殺死會話SQL會話