面试题答案
一键面试间隙锁导致死锁的原理
在MySQL中,间隙锁(Gap Lock)是InnoDB存储引擎在可重复读隔离级别下为了解决幻读问题引入的一种锁机制。当一个事务在某个范围内执行插入、更新或删除操作时,会对这个范围内的间隙加锁,防止其他事务在该间隙插入新的数据。
假设有两个事务 T1
和 T2
,它们都对相同范围的数据进行操作。例如:
T1
对范围[10, 20]
加间隙锁进行读操作。T2
对范围[15, 25]
加间隙锁进行写操作。
如果此时 T1
试图对 [15, 20]
进行写操作(因为间隙锁的存在,它需要等待 T2
释放锁),而 T2
又试图对 [10, 15]
进行读操作(它也需要等待 T1
释放锁),这样就形成了循环等待,从而导致死锁。
避免死锁的策略
- 按相同顺序访问资源
- 原理:所有事务按照固定的顺序访问数据,比如按照主键从小到大的顺序。这样可以避免循环等待的情况发生。例如,所有事务都先访问主键为1的数据,再访问主键为2的数据,以此类推。
- 优点:简单易懂,实现成本低,能有效避免死锁。
- 缺点:可能会降低并发性能,因为某些事务可能需要等待其他事务先完成对某些资源的操作,尤其是在资源访问顺序较为复杂的情况下。
- 降低事务隔离级别
- 原理:将隔离级别从可重复读(默认)降低到读已提交。在读已提交隔离级别下,InnoDB 存储引擎不会使用间隙锁,从而避免了因间隙锁导致的死锁。
- 优点:提高了并发性能,减少了锁的持有时间和范围。
- 缺点:可能会出现幻读问题,应用程序需要自己处理由此带来的数据一致性问题。
- 设置合理的锁超时时间
- 原理:设置一个合理的锁等待超时时间。当一个事务等待锁的时间超过这个设定值时,InnoDB 会自动回滚该事务,从而打破死锁。
- 优点:不需要对业务逻辑进行大量修改,MySQL 自身提供了这种机制,实现相对简单。
- 缺点:可能会导致一些正常的事务被回滚,尤其是在高并发场景下,锁等待时间可能经常超过设定值,增加了事务重试的成本。