MySQL 8.4 发行说明
当 死锁检测 启用(默认情况下)时,InnoDB
会自动检测事务 死锁 并回滚一个或多个事务以打破死锁。 InnoDB
尝试选择较小的事务进行回滚,其中事务的大小由插入、更新或删除的行数决定。
如果 innodb_table_locks = 1
(默认)并且 autocommit = 0
,则 InnoDB
会知道表级锁,并且它之上的 MySQL 层会知道行级锁。 否则,InnoDB
无法检测到涉及 MySQL LOCK TABLES
语句设置的表级锁或其他存储引擎(而非 InnoDB
)设置的锁的死锁。 通过设置 innodb_lock_wait_timeout
系统变量的值来解决这些情况。
如果 InnoDB
监控器输出的 LATEST DETECTED DEADLOCK
部分包含一条消息,指出 TOO DEEP OR LONG SEARCH IN THE LOCK TABLE WAITS-FOR GRAPH, WE WILL ROLL BACK FOLLOWING TRANSACTION,则表示等待列表上的事务数已达到 200 的限制。 超过 200 个事务的等待列表将被视为死锁,尝试检查等待列表的事务将被回滚。 如果锁定线程必须查看等待列表上事务拥有的超过 1,000,000 个锁,也会发生同样的错误。
有关组织数据库操作以避免死锁的技术,请参见 第 17.7.5 节,“InnoDB 中的死锁”。
在高并发系统中,当许多线程等待相同的锁时,死锁检测会导致速度变慢。 有时,禁用死锁检测并依赖 innodb_lock_wait_timeout
设置来回滚发生死锁时的事务,可能会更高效。 可以使用 innodb_deadlock_detect
变量禁用死锁检测。