mysql鎖之死鎖
死鎖是事務繞不開的話題,mysql當然也不例外,本文主要模擬一下mysql的死鎖,以及應對措施。
首先看一個引數,預設innodb_print_all_deadlocks引數是關閉。開啟後可以將死鎖記錄到error.log中。否則只能通過show engine innodb status檢視。
mysql> SHOW VARIABLES LIKE 'INNODB_PRINT_ALL_DEADLOCKS';
+----------------------------+-------+
| Variable_name | Value |
+----------------------------+-------+
| innodb_print_all_deadlocks | OFF |
+----------------------------+-------+
1 row in set (0.00 sec)
開啟innodb_print_all_deadlocks,改引數是全域性引數,可以動態調整。
mysql> SET GLOBAL innodb_print_all_deadlocks=1;
Query OK, 0 rows affected (0.00 sec)
表test01上c1是主鍵,c2是唯一約束。
mysql> show create table test01\G
*************************** 1. row ***************************
Table: test01
Create Table: CREATE TABLE `test01` (
`c1` bigint(20) NOT NULL AUTO_INCREMENT,
`c2` int(11) DEFAULT NULL,
PRIMARY KEY (`c1`),
UNIQUE KEY `uidx_test01_c2` (`c2`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
mysql> select * from test01;
+----+------+
| c1 | c2 |
+----+------+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
+----+------+
3 rows in set (0.00 sec)
會話A
mysql> begin ;
Query OK, 0 rows affected (0.00 sec)
mysql> delete from test01 where c2=2;
Query OK, 1 row affected (0.00 sec)
會話B
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> delete from test01 where c2=2;
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction
會話A
mysql> insert into test01 select 2,2;
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0
會話A在(2,2)上加了X的行鎖,會話B要刪除相同的資料行,那麼也要在該行上加X的行鎖(lock_mode X locks rec but not gap),所以出現了等待(lock_mode X waiting)。後面會話A要插入一行(2,2),因為欄位c2上有唯一索引,插入的時候要檢查duplicate key的檢查,這個過程需要申請S的鎖,而在得到這個鎖之前,它需要等會話B先得到會話A最開始執行的X鎖。也就是說,會話B要等待會話A第一條語句釋放X鎖,會話A第二條語句又要等待會話B釋放X鎖,兩個會話之間形成了等待的閉合迴路,形成了死鎖。出現死鎖後,mysql會選擇一個小事務進行回滾,以解決死鎖。
show engine innodb status檢視死鎖資訊,error.log中記錄的死鎖也類似下面:
------------------------
LATEST DETECTED DEADLOCK
------------------------
2019-07-18 11:11:32 0x7fdc50298700
*** (1) TRANSACTION:
TRANSACTION 713521, ACTIVE 122 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 2 lock struct(s), heap size 1136, 2 row lock(s)
MySQL thread id 4, OS thread handle 140584214165248, query id 144 localhost root updating
delete from test01 where c2=2
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 25 page no 4 n bits 72 index uidx_test01_c2 of table `ming`.`test01` trx id 713521 lock_mode X waiting
Record lock, heap no 3 PHYSICAL RECORD: n_fields 2; compact format; info bits 32
0: len 4; hex 80000002; asc ;;
1: len 8; hex 8000000000000002; asc ;;
*** (2) TRANSACTION:
TRANSACTION 713523, ACTIVE 16 sec inserting
mysql tables in use 1, locked 1
4 lock struct(s), heap size 1136, 3 row lock(s), undo log entries 2
MySQL thread id 3, OS thread handle 140584214431488, query id 146 localhost root executing
insert into test01 select 2,2
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 25 page no 4 n bits 72 index uidx_test01_c2 of table `ming`.`test01` trx id 713523 lock_mode X locks rec but not gap
Record lock, heap no 3 PHYSICAL RECORD: n_fields 2; compact format; info bits 32
0: len 4; hex 80000002; asc ;;
1: len 8; hex 8000000000000002; asc ;;
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 25 page no 4 n bits 72 index uidx_test01_c2 of table `ming`.`test01` trx id 713523 lock mode S waiting
Record lock, heap no 3 PHYSICAL RECORD: n_fields 2; compact format; info bits 32
0: len 4; hex 80000002; asc ;;
1: len 8; hex 8000000000000002; asc ;;
針對死鎖的舉措:
1.如果死鎖較多的話,那麼建議開啟innodb_print_all_deadlocks,因為show engine innodb status只顯示最近一次的死鎖資訊。
2.保持事務小而短,並儘快提價
3.避免在一個事務裡面修改幾張表,或者是同一張表修改不同的結果集
4.可以嘗試使用較低的隔離級別,比如RC。也可以使用鎖定讀
5.建立合適的索引
6.如果應用允許的話,序列化事務
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31480688/viewspace-2651193/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 面試題之死鎖解密面試題解密
- 併發程式設計之死鎖解析程式設計
- MySQL鎖(樂觀鎖、悲觀鎖、多粒度鎖)MySql
- MySQL全域性鎖、表鎖以及行鎖MySql
- MySQL 死鎖和鎖等待MySql
- mysql 鎖MySql
- [Mysql]鎖MySql
- MySQL鎖MySql
- 多執行緒之死鎖就是這麼簡單執行緒
- Mysql鎖之行級鎖和表級意向鎖MySql
- 【問答分享第一彈】MySQL鎖總結:MySQL行鎖、表鎖、排他鎖、共享鎖的特點MySql
- MySQL 全域性鎖和表鎖MySql
- MySQL鎖:03.InnoDB行鎖MySql
- MySQL 行級鎖之 間隙鎖、臨鍵鎖MySql
- MySQL鎖(讀鎖、共享鎖、寫鎖、S鎖、排它鎖、獨佔鎖、X鎖、表鎖、意向鎖、自增鎖、MDL鎖、RL鎖、GL鎖、NKL鎖、插入意向鎖、間隙鎖、頁鎖、悲觀鎖、樂觀鎖、隱式鎖、顯示鎖、全域性鎖、死鎖)MySql
- MySQL/InnoDB中,樂觀鎖、悲觀鎖、共享鎖、排它鎖、行鎖、表鎖、死鎖概念的理解MySql
- MySQL -- 表鎖MySql
- MySQL -- 行鎖MySql
- MySQL表鎖MySql
- MySQL 四 鎖MySql
- MySQL 行鎖MySql
- MySQL鎖分析MySql
- MySQL 鎖bug?MySql
- MySQL的鎖MySql
- MySQL索引失效行鎖變表鎖MySql索引
- mysql行鎖和死鎖檢測MySql
- MySQL的共享鎖和獨佔鎖MySql
- Mysql 兩階段鎖和死鎖MySql
- MySQL鎖(四)行鎖的加鎖規則和案例MySql
- 【MySQL】MySQL中的鎖MySql
- MySQL記錄鎖、間隙鎖、臨鍵鎖小案例演示MySql
- MySQL行鎖、表鎖、間隙鎖,你都瞭解嗎MySql
- MySQL 共享鎖 (lock in share mode),排他鎖 (for update)MySql
- mysql for update是鎖表還是鎖行MySql
- Mysql中的鎖機制——MyISAM表鎖MySql
- MySQL鎖:InnoDB行鎖需要避免的坑MySql
- MySQL鎖問題分析-全域性讀鎖MySql
- MySQL鎖等待與死鎖問題分析MySql