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


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET 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?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
