什么场景会出现死锁
两个或者两个以上的事务在执行过程中,出现了因为争夺资源造成的一种互相等待情况。
共享锁死锁的情况
session1 | session2 |
---|---|
set autocommit =0; | set autocommit =0; |
select * from edu_user lock in share mode; | select * from edu_user lock in share mode; |
阻塞:update edu_user set password="456789" where username = "王五"; | |
报错:update edu_user set password="012345" where username = "王五"; | |
自动结束当前事务:1213 - Deadlock found when trying to get lock; try restarting transaction | |
commit; |
说明:
session1和session2都开启事务后,都获取了同一把共享锁,但是session1写操作需要对方阻塞,等待。session2写操作同样需要对方阻塞,等待。两个都饥饿获取不到锁,产生了死锁。
排他锁死锁的情况
session1 | session2 |
---|---|
set autocommit =0; | |
select * from edu_user where id = 1 for update; | set autocommit =0; |
select * from edu_user where id = 2 for update; | |
阻塞等待:select * from edu_user where id = 2 for update; | |
select * from edu_user where id = 1 for update; | |
1213 - Deadlock found when trying to get lock; try restarting transaction |
说明:
session1和session都手动提交事务时,session1获取了id为1的记录的排他锁,session2获取了id为2的记录的排他锁。那么session1再想获取id为2的排他锁只能等待session2释放锁,session2再想获取id为1的排他锁只能等待session1释放锁。双方都等待对方释放锁,那么就互相都饥饿,获取不到锁,产生了死锁。
解决方法1,手动整个事务回滚
mysql> rollback;
Query OK, 0 rows affected (0.00 sec)
解决方法2,设置超时回滚
# 说明:事务等待行锁定的时间,默认值为50秒。发生锁定等待超时,将回滚当前语句。
innodb_lock_wait_timeout
#说明:InnoDB默认情况下只会回滚事务超时的最后一个语句。指定这个参数将回滚整个事务。
innodb_rollback_on_timeout
网友评论