Skip to content

Latest commit

 

History

History
28 lines (15 loc) · 1.81 KB

数据库-mysql-死锁.md

File metadata and controls

28 lines (15 loc) · 1.81 KB

InnoDB 死锁

死锁是一种不同事务无法继续进行的情况,核心原因是每个事务都持有某个另一个事务所需的锁。因为双方事务都在等待资源变为可用状态,所以它们都不会释放它所持有的锁。

当事务锁定多个表中的行(通过 UPDATESELECT ... FOR UPDATE 等语句),但彼此加锁的顺序相反时,可能会发生死锁。当这样的语句锁定索引记录和间隙的范围时,也会发生死锁,因为每个事务都会由于时序问题获得部分锁,而获取不了其他范围的锁。

为了减少死锁的可能性,可以采取以下措施:

  • 应使用事务而不是锁表语句。

  • 将插入或更新数据的事务保持在足够小的范围内,使其不会长时间处于打开状态。

  • 当不同的事务更新多个表或大范围的行时,在每个事务中使用相同的操作顺序(例如 SELECT ... FOR UPDATE

  • 在使用 SELECT ... FOR UPDATEUPDATE ... WHERE 的列上创建索引

发生死锁的可能性不受隔离级别的影响,因为隔离级别会更改读取操作的行为,而死锁是由于写入操作而发生的。

当启用死锁检测(默认开启)且死锁确实发生时,InnoDB 检测到该情况并回滚其中一个事务。如果使用 innodb_deadlock_detect 变量禁用死锁检测,innodb 将基于 innodb_lock_wait_timeout 配置在发生死锁时回滚事务。因此,即使应用程序逻辑正确,也必须处理必须重试事务的情况。

要查看 InnoDB 用户事务中的最后一个死锁,请使用 SHOW ENGINE INNODB STATUS

如果频繁的死锁,这说明事务结构或应用程序存在错误逻辑,请启用 innodb_print_all_deadlocks 将所有死锁的信息打印到 mysqld 错误日志中。

如何减少和处理死锁问题