网上很多介绍死锁原理有排查方法,但是如何排查哪个事务阻塞导致死锁的发生,网上大佬的级别太高,我们新手看的是云里来雾里云的
以参考文档中的例子,环境准备也一样
1、数据库隔离级别
mysql> select @@tx_isolation;
+-----------------+
| @@tx_isolation |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set, 1 warning (0.00 sec)
2、关闭事务自动提交
mysql> select @@autocommit;
+--------------+
| @@autocommit |
+--------------+
| 1 |
+--------------+
1 row in set (0.00 sec)
mysql> set @@autocommit=0;
Query OK, 0 rows affected (0.01 sec)
mysql> select @@autocommit;
+--------------+
| @@autocommit |
+--------------+
| 0 |
+--------------+
1 row in set (0.00 sec)
表结构:
//id是自增主键,name是非唯一索引,balance普通字段
CREATE TABLE `account` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`balance` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_name` (`name`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
insert into account values(null,'Z3',1);
insert into account values(null,'L4',1);
模拟并发制造死锁现场
事务A
mysql> update account set balance=2 where name='Z3';
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
事务B
mysql> mysql> update account set balance=2 where name='L4';
#事务A
mysql> insert into account values(null,'W5',1);
mysql> select * from information_schema.innodb_lock_waits\G
*************************** 1. row ***************************
requesting_trx_id: 5486
requested_lock_id: 5486:31:4:2
blocking_trx_id: 5487
blocking_lock_id: 5487:31:4:2
1 row in set, 1 warning (0.00 sec)
mysql> SELECT trx_mysql_thread_id FROM information_schema.innodb_trx where trx_id=5487;
+---------------------+
| trx_mysql_thread_id |
+---------------------+
| 18 |
+---------------------+
1 row in set (0.00 sec)
kill阻塞进程
mysql> kill 18;
查询未提交的事务
select * from performance_schema.events_statements_current\G
上述的kill方案,还是存在一点没有连接上,能找到trx_mysql_thread_id,但是无法与events_statements_current表示的信息连,这样就无法快速的确认阻塞的sql