mysql死锁的条件及应对措施

死锁,就是产生了循环等待链条,我等待你的资源,你却等待我的资源,我们都相互等待,谁也不释放自己占有的资源,导致无线等待下去。

案例

批量更新/删除,使用in导致的死锁

批量更新数据时,我猜你会使用in关键字,这种批量更新,可能会导致MySQL死锁,为什么?因为间隙锁的问题,导致间隙锁的范围会重叠。 解决方案:使用INSERT INTO ... VALUES ... ON DUPLICATE KEY UPDATE ...的语法,当键重复时更新某些值,详细用法参见MySQL ON DUPLICATE KEY UPDATE的用法 。主键使用or连接,但要注意,所有主键必须都存在,否则会有间隙锁,出现死锁。

高并发时,先删除在插入的代码导致的死锁

详细问题及解决方案参见MySQL InnoDB(Spring)并发事务导致的死锁及解决方案

如何尽可能避免死锁

1)以固定的顺序访问表和行。比如两个更新数据的事务,事务A 更新数据的顺序 为1,2;事务B更新数据的顺序为2,1。这样更可能会造成死锁。

2)大事务拆小。大事务更倾向于死锁,如果业务允许,将大事务拆小。

3)在同一个事务中,尽可能做到一次锁定所需要的所有资源,减少死锁概率。

4)降低隔离级别。如果业务允许,将隔离级别调低也是较好的选择,比如将隔离级别从RR调整为RC,可以避免掉很多因为gap锁造成的死锁。

5)为表添加合理的索引。可以看到如果不走索引将会为表的每一行记录添加上锁,死锁的概率大大增大。批量更新/删除,使用in导致的死锁 批量更新数据时,我猜你会使用in关键字,这种批量更新,可能会导致MySQL死锁,为什么?因为间隙锁的问题,导致间隙锁的范围会重叠。 解决方案:使用INSERT INTO ... VALUES ... ON DUPLICATE KEY UPDATE ...的语法,当键重复时更新某些值,详细用法参见MySQL ON DUPLICATE KEY UPDATE的用法 。在MySQL的低版本中(貌似是5.1之前的,具体版本记不清了),这个语法也可能出现死锁的问题。我的MySQL版本是5.6.19。 解决方案:主键使用or连接,但要注意,所有主键必须都存在,否则会有间隙锁,出现死锁。

Last updated