mysql死锁

什么场景会出现死锁


两个或者两个以上的事务在执行过程中,出现了因为争夺资源造成的一种互相等待情况。

共享锁死锁的情况

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

你可能感兴趣的:(mysql死锁)