14.7.5.2 死锁检测和回滚

启用deadlock detection时(默认设置),InnoDB自动检测到事务deadlocks并回滚一个或多个事务以 break 僵局。 InnoDB尝试选择要回滚的小事务,其中事务的大小由插入,更新或删除的行数确定。

如果innodb_table_locks = 1(默认值)和自动提交= 0InnoDB知道 table 锁,并且它上面的 MySQL 层知道行级锁。否则,InnoDB无法检测到涉及 MySQL LOCK TABLES语句设置的 table 锁或InnoDB以外的存储引擎设置的锁的死锁。通过设置innodb_lock_wait_timeout系统变量的值来解决这些情况。

InnoDB执行事务的完全回滚时,将释放该事务设置的所有锁。但是,如果由于错误而仅回滚单个 SQL 语句,则可以保留该语句设置的某些锁。发生这种情况是因为InnoDB以某种格式存储行锁,使得以后不知道哪个语句设置了哪个锁。

如果SELECT在事务中调用存储的函数,并且函数内的语句失败,则该语句将回滚。此外,如果此后执行ROLLBACK,则整个事务都会回滚。

如果InnoDB Monitor 输出的LATEST DETECTED DEADLOCK部分包含一条消息,指出“锁定 tableawait 太深或长时间搜索-图形,我们将回滚后续 Transaction”,这 table 明 await 列 table 上的 Transaction 数量已达到达到限制 200.超过 200 个事务的 await 列 table 将被视为死锁,并且尝试检查 await 列 table 的事务将回退。如果锁定线程必须查看 await 列 table 上的事务拥有的 1,000,000 个以上的锁,也可能发生相同的错误。

有关组织数据库操作以避免死锁的技术,请参见第 14.7.5 节“ InnoDB 中的死锁”

禁用死锁检测

在高并发系统上,当多个线程 await 相同的锁时,死锁检测会导致速度变慢。有时,禁用死锁检测并在发生死锁时依靠innodb_lock_wait_timeout设置进行事务回滚可能会更有效。可以使用innodb_deadlock_detect配置选项禁用死锁检测。