Mysql - 死锁
2020-04-01 本文已影响0人
万福来
Mysql - 死锁
死锁,就是产生了循环等待链条,我等待你释放锁,你却等待我释放锁,我们都相互等待,谁也不释放自己的锁,导致无限等待下去。比如:
//Session A
START TRANSACTION;
UPDATE account SET p_money=p_money-100 WHERE p_name="tim";
UPDATE account SET p_money=p_money+100 WHERE p_name="bill";
COMMIT;
//Thread B
START TRANSACTION;
UPDATE account SET p_money=p_money+100 WHERE p_name="bill";
UPDATE account SET p_money=p_money-100 WHERE p_name="tim";
COMMIT;
innodb_lock_wait_timeout 等待锁超时回滚事务:
直观方法是在两个事务相互等待时,当一个等待时间超过设置的某一阀值时,对其中一个事务进行回滚,另一个事务就能继续执行。这种方法简单有效,在innodb中,参数innodb_lock_wait_timeout用来设置超时时间。
wait-for graph算法来主动进行死锁检测:
innodb还提供了wait-for graph算法来主动进行死锁检测,每当加锁请求无法立即满足需要并进入等待时,wait-for graph算法都会被触发。
如何避免死锁
- 以固定的顺序访问表和行。比如两个事务更新数据,事务A更新数据顺序为1、2,但是事务B更新数据顺序为2、1。这样可能会造成死锁。
- 大事务拆分成小事务,大事务发生死锁的概率更大一些。
- 在同一个事务中,尽可能一次锁定所需要的所有资源,减少死锁概率。
- 降低隔离级别,如果业务运行的情况下,比如将隔离级别从RR调整为RC,可以避免因为gap锁造成的死锁。
- 为表添加合理的索引,如果不走索引,将会为表的每一行记录添加锁,死锁的概率增大。