> For the complete documentation index, see [llms.txt](https://bing.gitbook.io/phper/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://bing.gitbook.io/phper/data-base/my-sql/shi-wu-he-suo/mysql-si-suo-de-tiao-jian-ji-ying-dui-cuo-shi.md).

# mysql死锁的条件及应对措施

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

### 案例

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

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

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

详细问题及解决方案参见[MySQL InnoDB（Spring）并发事务导致的死锁及解决方案](https://blog.csdn.net/qq_30038111/article/details/85480791) 。

### 如何尽可能避免死锁

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连接，但要注意，所有主键必须都存在，否则会有间隙锁，出现死锁。
