面试题答案
一键面试MySQL数据库内部死锁检测方式
- 超时等待:当事务等待锁的时间超过设定的超时时间(innodb_lock_wait_timeout参数),就认为发生死锁,等待的事务将被回滚。这是一种简单粗暴但并非严格意义上检测死锁的方式。
- 死锁检测算法:InnoDB使用wait-for graph(等待图)算法来主动检测死锁。InnoDB会在每个事务请求锁并进入等待状态时,将相关信息加入等待图。等待图是一个有向图,图中的节点是事务,边表示事务之间的等待关系。例如,如果事务T1等待事务T2持有的锁,那么就有一条从T1指向T2的边。InnoDB会定期检查等待图中是否存在环,如果存在环,就说明发生了死锁。此时,InnoDB会选择回滚代价最小的事务来解除死锁。
检测机制背后原理
- 资源竞争:死锁发生的根本原因是多个事务对资源(如锁)的竞争,并且这种竞争形成了循环等待的关系。通过检测等待图中的环,可以发现这种循环等待情况。
- 回滚策略:选择回滚代价最小的事务,是为了尽量减少对整个系统运行的影响。回滚代价通常基于事务已经修改的数据量、事务已持有的锁数量等因素来衡量。
检测过程中涉及的关键数据结构
- 锁结构(lock struct):用于描述锁的信息,包括锁的类型(共享锁、排他锁等)、锁所在的对象(表、行等)、持有锁的事务等。每个锁结构会被链入相应的哈希表中,方便快速查找。
- 事务结构(trx struct):包含了事务的各种信息,如事务ID、事务状态(活跃、提交、回滚等)、事务持有的锁列表以及等待的锁列表等。事务结构用于跟踪事务的执行情况以及它与锁的关系。
- 等待图(wait-for graph):是检测死锁的核心数据结构,它以有向图的形式记录了事务之间的等待关系。通过维护这个图,InnoDB可以高效地检测是否存在死锁环。