模拟死锁案例

查看系统环境

#查看死锁参数
show variables like '%deadlock%';
#开启记录死锁
set global innodb_print_all_deadlocks=1;

#查看隔离级别
SHOW VARIABLES LIKE '%isolation%';
#查看是否自动提交
SHOW VARIABLES LIKE '%auto%';
环境为RR隔离级别,默认自动提交,语句显示开启事务
View Code

创建测试表并插入测试数据

#创建测试表并插入测试数据
use test;
CREATE TABLE `test` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `a` int(11) unsigned DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `a` (`a`)
) ENGINE=InnoDB AUTO_INCREMENT=100 DEFAULT CHARSET=utf8;
insert into `test` values(1,1),(2,2),(4,4);
View Code

在对应的连接中执行下面语句

#连接1
begin;
delete from test where a = 2;
#连接2
begin;
delete from test where a = 2; 
#连接1
insert into test (id, a) values (10, 2);
View Code


此时在错误日志中可以看到下面的信息

2017-02-24 17:45:54 1fbcInnoDB: transactions deadlock detected, dumping detailed information.
2017-02-24 17:45:54 1fbc
*** (1) TRANSACTION:
TRANSACTION 3445, ACTIVE 9 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 2 lock struct(s), heap size 312, 1 row lock(s)
MySQL thread id 16, OS thread handle 0x1e04, query id 261 localhost 127.0.0.1 root updating
delete from test where a = 2
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 12 page no 4 n bits 72 index `a` of table `test`.`test` trx id 3445 lock_mode X waiting
Record lock, heap no 3 PHYSICAL RECORD: n_fields 2; compact format; info bits 32
 0: len 4; hex 00000002; asc     ;;
 1: len 4; hex 00000002; asc     ;;

*** (2) TRANSACTION:
TRANSACTION 3444, ACTIVE 12 sec inserting
mysql tables in use 1, locked 1
4 lock struct(s), heap size 312, 3 row lock(s), undo log entries 2
MySQL thread id 15, OS thread handle 0x1fbc, query id 262 localhost 127.0.0.1 root update
insert into test (id, a) values (10, 2)
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 12 page no 4 n bits 72 index `a` of table `test`.`test` trx id 3444 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 00000002; asc     ;;
 1: len 4; hex 00000002; asc     ;;

*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 12 page no 4 n bits 72 index `a` of table `test`.`test` trx id 3444 lock mode S waiting
Record lock, heap no 3 PHYSICAL RECORD: n_fields 2; compact format; info bits 32
 0: len 4; hex 00000002; asc     ;;
 1: len 4; hex 00000002; asc     ;;

*** WE ROLL BACK TRANSACTION (1)
View Code

分析

步骤 连接1 连接2
1 begin;   
2 delete from test where a = 2; 执行成功,连接1占有a=2下的X锁,类型为记录锁。   
3   begin; 
4   delete from test where a = 2; 连接2希望申请a=2下的X锁,但是由于连接1已经申请了一把X锁,两把X锁互斥,所以X锁申请进入锁请求队列。 
5 insert into test (id, a) values (10, 2); 由于a字段建立了唯一索引,所以需要申请S锁以便检查duplicate key,由于插入的a的值还是2,所以排在X锁后面。但是前面的X锁的申请只有在连接1commit或者rollback之后才能成功,此时形成了循环等待,死锁产生。 出现死锁,连接2权重较小,所以被选择回滚(成为牺牲品)。
posted @ 2017-02-24 18:11  醒嘞  阅读(312)  评论(0编辑  收藏  举报