MySQL:死鎖一例
歡迎關注我的專欄《深入理解MySQL主從原理 32講》
具體可以點選:ttps://j.youzan.com/yEY_Xi
一、問題由來
這是我同事問我的一個問題,在網上看到了如下案例,本案例RC RR都可以出現,其實這個死鎖原因也不叫簡單,我們來具體看看:
構造資料
CREATE database deadlock_test;
use deadlock_test;
CREATE TABLE `push_token` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`token` varchar(128) NOT NULL COMMENT 'push token',
`app_id` varchar(128) DEFAULT NULL COMMENT 'appid',
`deleted` tinyint(1) NOT NULL COMMENT '是否已刪除 0:否 1:是',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_token_appid` (`token`,`app_id`)
) ENGINE=InnoDB AUTO_INCREMENT=3384 DEFAULT CHARSET=utf8 COMMENT='pushtoken表';
insert into push_token (id, token, app_id, deleted) values(1,"token1",1,0);
運算元據
s1(TRX_ID367661) | s2(TRX_ID367662) | s3(TRX_ID367663) |
---|---|---|
begin; UPDATE push_token SET deleted = 1 WHERE token = ‘token1’ AND app_id = ‘1’; | ||
begin; DELETE FROM push_token WHERE id IN (1); | ||
begin; UPDATE push_token SET deleted = 1 WHERE token = ‘token1’ AND app_id = ‘1’; | ||
commit; | ||
Query OK, 0 rows affected (0.00 sec) | Query OK, 1 row affected (17.32 sec) | ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction |
二、分析方法
我使用的分析方法是把整個加鎖的日誌列印出來,當然需要用到我自己做了輸出修改的一個版本,如下:
https://github.com/gaopengcarl/percona-server-locks-detail-5.7.22
這個版本我開啟了的日誌記錄引數如下:
mysql> show variables like '%gaopeng%';
+--------------------------------+-------+
| Variable_name | Value |
+--------------------------------+-------+
| gaopeng_mdl_detail | OFF |
| innodb_gaopeng_row_lock_detail | ON |
+--------------------------------+-------+
2 rows in set (0.01 sec)
這樣大部分的innodb加鎖記錄都會記錄到errlog日誌了。好了下面我詳細分析一下日誌:
三、分析過程
初始化的情況整個表只有1條記錄,本表包含一個主鍵和一個唯一鍵。
begin;
UPDATE push_token SET deleted = 1 WHERE token = 'token1' AND app_id = '1';
日誌輸出:
2019-08-18T19:10:05.117317+08:00 6 [Note] InnoDB: TRX ID:(367661) table:deadlock_test/push_token index:uk_token_appid space_id: 449 page_id:4 heap_no:2 row lock mode:LOCK_X|LOCK_NOT_GAP|
PHYSICAL RECORD: n_fields 3; compact format; info bits 0
0: len 6; hex 746f6b656e31; asc token1;;
1: len 1; hex 31; asc 1;;
2: len 8; hex 8000000000000001; asc ;;
2019-08-18T19:10:05.117714+08:00 6 [Note] InnoDB: TRX ID:(367661) table:deadlock_test/push_token index:PRIMARY space_id: 449 page_id:3 heap_no:2 row lock mode:LOCK_X|LOCK_NOT_GAP|
PHYSICAL RECORD: n_fields 6; compact format; info bits 0
0: len 8; hex 8000000000000001; asc ;;
1: len 6; hex 000000059c2c; asc ,;;
2: len 7; hex bf000000420110; asc B ;;
3: len 6; hex 746f6b656e31; asc token1;;
4: len 1; hex 31; asc 1;;
5: len 1; hex 80; asc ;;
我們看到主鍵和唯一鍵都加鎖瞭如下圖:
begin;DELETE FROM push_token WHERE id IN (1);
`
日誌輸出:
2019-08-18T19:10:22.751467+08:00 9 [Note] InnoDB: TRX ID:(367662) table:deadlock_test/push_token index:PRIMARY space_id: 449 page_id:3 heap_no:2 row lock mode:LOCK_X|LOCK_NOT_GAP|
PHYSICAL RECORD: n_fields 6; compact format; info bits 0
0: len 8; hex 8000000000000001; asc ;;
1: len 6; hex 000000059c2d; asc -;;
2: len 7; hex 400000002a1dc8; asc @ * ;;
3: len 6; hex 746f6b656e31; asc token1;;
4: len 1; hex 31; asc 1;;
5: len 1; hex 81; asc ;;
2019-08-18T19:10:22.752753+08:00 9 [Note] InnoDB: Trx(367662) is blocked!!!!!
這個時候S2需要獲取主鍵上的鎖,因此被堵塞瞭如下圖:
begin; UPDATE push_token SET deleted = 1 WHERE token = 'token1' AND app_id = '1';
`
日誌輸出:
019-08-18T19:10:30.822111+08:00 8 [Note] InnoDB: TRX ID:(367663) table:deadlock_test/push_token index:uk_token_appid space_id: 449 page_id:4 heap_no:2 row lock mode:LOCK_X|LOCK_NOT_GAP|
PHYSICAL RECORD: n_fields 3; compact format; info bits 0
0: len 6; hex 746f6b656e31; asc token1;;
1: len 1; hex 31; asc 1;;
2: len 8; hex 8000000000000001; asc ;;
2019-08-18T19:10:30.918248+08:00 8 [Note] InnoDB: Trx(367663) is blocked!!!!!
這個時候S3需要獲取唯一鍵上的鎖,因此被堵塞瞭如下圖:
這一步完成後死鎖出現。
commit;
日誌輸出如下:
367663和367662各自獲取需要的鎖
2019-08-18T19:10:36.566733+08:00 8 [Note] InnoDB: TRX ID:(367663) table:deadlock_test/push_token index:uk_token_appid space_id: 449 page_id:4 heap_no:2 row lock mode:LOCK_X|LOCK_NOT_GAP|
PHYSICAL RECORD: n_fields 3; compact format; info bits 0
0: len 6; hex 746f6b656e31; asc token1;;
1: len 1; hex 31; asc 1;;
2: len 8; hex 8000000000000001; asc ;;
2019-08-18T19:10:36.568711+08:00 9 [Note] InnoDB: TRX ID:(367662) table:deadlock_test/push_token index:PRIMARY space_id: 449 page_id:3 heap_no:2 row lock mode:LOCK_X|LOCK_NOT_GAP|
PHYSICAL RECORD: n_fields 6; compact format; info bits 0
0: len 8; hex 8000000000000001; asc ;;
1: len 6; hex 000000059c2d; asc -;;
2: len 7; hex 400000002a1dc8; asc @ * ;;
3: len 6; hex 746f6b656e31; asc token1;;
4: len 1; hex 31; asc 1;;
5: len 1; hex 81; asc ;;
367663獲取主鍵鎖堵塞、367662獲取唯一鍵鎖堵塞,死鎖形成
2019-08-18T19:10:36.570313+08:00 8 [Note] InnoDB: TRX ID:(367663) table:deadlock_test/push_token index:PRIMARY space_id: 449 page_id:3 heap_no:2 row lock mode:LOCK_X|LOCK_NOT_GAP|
PHYSICAL RECORD: n_fields 6; compact format; info bits 0
0: len 8; hex 8000000000000001; asc ;;
1: len 6; hex 000000059c2d; asc -;;
2: len 7; hex 400000002a1dc8; asc @ * ;;
3: len 6; hex 746f6b656e31; asc token1;;
4: len 1; hex 31; asc 1;;
5: len 1; hex 81; asc ;;
2019-08-18T19:10:36.571199+08:00 8 [Note] InnoDB: Trx(367663) is blocked!!!!!
2019-08-18T19:10:36.572481+08:00 9 [Note] InnoDB: TRX ID:(367662) table:deadlock_test/push_token index:uk_token_appid space_id: 449 page_id:4 heap_no:2 row lock mode:LOCK_X|LOCK_NOT_GAP|
PHYSICAL RECORD: n_fields 3; compact format; info bits 0
0: len 6; hex 746f6b656e31; asc token1;;
1: len 1; hex 31; asc 1;;
2: len 8; hex 8000000000000001; asc ;;
2019-08-18T19:10:36.573073+08:00 9 [Note] InnoDB: Transactions deadlock detected, dumping detailed information.
這個時候我們看到s2和s3先是獲取了各自需要的鎖,s3獲取主鍵鎖堵塞,s2獲取唯一鍵鎖堵塞,死鎖出現。如下圖:
好了我們看到了死鎖就這樣出現。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/7728585/viewspace-2651186/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Oracle死鎖一例(ORA-00060),鎖表導致的業務死鎖問題Oracle
- MySQL 死鎖和鎖等待MySql
- 面試:什麼是死鎖,如何避免或解決死鎖;MySQL中的死鎖現象,MySQL死鎖如何解決面試MySql
- MySQL 死鎖解決MySql
- MySQL解決死鎖MySql
- MySQL死鎖問題MySql
- MySQL死鎖系列-線上死鎖問題排查思路MySql
- mysql行鎖和死鎖檢測MySql
- Mysql 兩階段鎖和死鎖MySql
- mysql死鎖最佳化MySql
- MySQL 死鎖問題分析MySql
- 【MySQL】死鎖案例之六MySql
- 【MySQL】死鎖案例之七MySql
- 【MySQL】死鎖案例之八MySql
- Mysql如何處理死鎖MySql
- MySQL列印死鎖日誌MySql
- MySQL:MTS和mysqldump死鎖MySql
- MySQL:一個死鎖分析 (未分析出來的死鎖)MySql
- MySQL鎖等待與死鎖問題分析MySql
- 故障分析 | MySQL鎖等待超時一例分析MySql
- MySQL:Innodb 一個死鎖案例MySql
- MySQL批量更新死鎖案例分析MySql
- MySQL insert on duplicate key update 死鎖MySql
- 故障分析 | MySQL死鎖案例分析MySql
- MySQL死鎖案例一(回滾導致死鎖)MySql
- MySQL死鎖案例二(自增列導致死鎖)MySql
- 剖析6個MySQL死鎖案例的原因以及死鎖預防策略MySql
- MySQL強人“鎖”難《死磕MySQL系列 三》MySql
- MySQL死鎖系列-常見加鎖場景分析MySql
- MySQL:RR分析死鎖一列MySql
- MySQL死鎖分析與解決之路MySql
- mysql慢查詢,死鎖解決方案MySql
- MySQL:RR模式下死鎖一列MySql模式
- 記一次線上mysql死鎖MySql
- 線上BUG:MySQL死鎖分析實戰MySql
- 聊聊MySQL的加鎖規則《死磕MySQL系列 十五》MySql
- MySQL死鎖案例分析一(先delete,再insert,導致死鎖)MySqldelete
- 死鎖