死锁是指两个或多个事务在同一资源上相互占用,并请求锁定对方占用的资源,从而导致恶性循环的现象。

为了解决这种问题,数据库系统实现了各种死锁检测死锁超时机制。越复杂的系统,比如 InnoDB 存储引擎,越能检测到死锁的循环依赖,并立即返回一个错误。这种解决方式很有效,否则死锁会导致出现非常慢的查询。还有一种解决方式,就是当查询的时间达到锁等待超时的设定后放弃锁请求,例如:

1
1205 - Lock wait timeout exceeded; try restarting transaction

InnoDB 目前处理死锁的方法是,将持有最少行级排它锁的事务进行回滚,这是相对比较简单的死锁回滚算法。

锁的行为和顺序是和存储引擎相关的。以同样的顺序执行语句,有些存储引擎会产生死锁,有些则不会。死锁的产生有双重原因:

  1. 有些是因为真正的数据冲突,这种情况通常很难避免。
  2. 有些则完全是由于存储引擎的实现方式导致的。

死锁发生以后,只有部分或者完全回滚其中一个事务,才能打破死锁。对于事务型的系统,这是无法避免的,所以应用程序在设计时必须考虑如何处理死锁。大多数情况下只需要重新执行因死锁回滚的事务即可。

同时,为了避免产生死锁问题,根源在于程序设计时要注意不同事务间 SQL 语句的执行顺序,避免互相锁住对方的资源。

参考

https://dev.mysql.com/doc/refman/5.7/en/innodb-deadlocks.html