死锁是一种情况,在这种情况下,多个事务无法继续进行,因为每个事务都持有另一个事务所需的锁。由于所有涉及的事务都在等待同一资源变得可用,所以它们没有一个会释放自己持有的锁。A deadlock is a situation in which multiple transactions are unable to proceed because each transaction holds a lock that is needed by another one. Because all transactions involved are waiting for the same resource to become available, none of them ever releases the lock it holds.
当事务以相反的顺序锁定多个表中的行(通过诸如 UPDATE 或 SELECT ... FOR
UPDATE 等语句)时,可能会发生死锁。当这些语句锁定索引记录和间隙的范围时,也可能发生死锁,每个事务由于时间问题而获取了一些锁但没有获取其他锁。有关死锁示例,请参见 第 17.7.5.1 节,“一个 InnoDB 死锁示例”。A deadlock can occur when transactions lock rows in multiple
tables (through statements such as
UPDATE or
SELECT ... FOR
UPDATE), but in the opposite order. A deadlock can also
occur when such statements lock ranges of index records and gaps,
with each transaction acquiring some locks but not others due to a
timing issue. For a deadlock example, see
Section 17.7.5.1, “An InnoDB Deadlock Example”.
为了减少死锁的可能性,应使用事务而不是LOCK TABLES语句;保持插入或更新数据的事务尽可能小,以免长时间保持开启;当不同事务更新多个表或大量行时,在每个事务中使用相同的操作顺序(例如SELECT ... FOR
UPDATE);在用于SELECT ...
FOR UPDATE和UPDATE ... WHERE语句的列上创建索引。死锁的可能性不会受隔离级别影响,因为隔离级别改变的是读操作的行为,而死锁发生是由于写操作。有关避免和恢复死锁条件的更多信息,请参见第 17.7.5.3 节,“如何最小化和处理死锁”。To reduce the possibility of deadlocks, use transactions rather
than LOCK TABLES statements; keep
transactions that insert or update data small enough that they do
not stay open for long periods of time; when different
transactions update multiple tables or large ranges of rows, use
the same order of operations (such as
SELECT ... FOR
UPDATE) in each transaction; create indexes on the
columns used in SELECT ...
FOR UPDATE and
UPDATE ... WHERE
statements. The possibility of deadlocks is not affected by the
isolation level, because the isolation level changes the behavior
of read operations, while deadlocks occur because of write
operations. For more information about avoiding and recovering
from deadlock conditions, see
Section 17.7.5.3, “How to Minimize and Handle Deadlocks”.
当启用死锁检测(默认设置)并且确实发生死锁时,InnoDB 会检测到该情况并回滚其中一个事务(受害者)。如果使用 innodb_deadlock_detect 变量禁用死锁检测,InnoDB 将依赖 innodb_lock_wait_timeout 设置在发生死锁时回滚事务。因此,即使你的应用逻辑是正确的,你仍然必须处理事务需要重试的情况。要查看 InnoDB 用户事务中的最后一次死锁,请使用 SHOW ENGINE INNODB
STATUS。如果频繁的死锁显示事务结构或应用错误处理存在问题,请启用 innodb_print_all_deadlocks,将所有死锁信息打印到 mysqld 错误日志中。有关死锁如何自动检测和处理的更多信息,请参见 第 17.7.5.2 节,“死锁检测”。When deadlock detection is enabled (the default) and a deadlock
does occur, InnoDB detects the condition and
rolls back one of the transactions (the victim). If deadlock
detection is disabled using the
innodb_deadlock_detect variable,
InnoDB relies on the
innodb_lock_wait_timeout setting
to roll back transactions in case of a deadlock. Thus, even if
your application logic is correct, you must still handle the case
where a transaction must be retried. To view the last deadlock in
an InnoDB user transaction, use
SHOW ENGINE INNODB
STATUS. If frequent deadlocks highlight a problem with
transaction structure or application error handling, enable
innodb_print_all_deadlocks to
print information about all deadlocks to the
mysqld error log. For more information about
how deadlocks are automatically detected and handled, see
Section 17.7.5.2, “Deadlock Detection”.