面试题答案
一键面试SQLite检测死锁的机制
SQLite使用递归深度优先搜索(DFS)算法来检测死锁。每当一个事务请求锁并且该锁由于其它事务持有而不可用时,SQLite会从这个事务开始,沿着锁依赖关系图进行DFS遍历。如果在遍历过程中发现一个事务已经在遍历路径中(即回到了自身),则检测到死锁。
死锁发生时的冲突解决策略
当检测到死锁时,SQLite会选择其中一个事务作为牺牲品(通常是执行时间较短的事务),回滚该事务,并向应用程序返回一个 SQLITE_BUSY
错误代码。应用程序可以捕获这个错误,然后决定是否重试该事务。
开发人员避免死锁的方法
- 按相同顺序获取锁:在多个事务中,始终按照相同的顺序请求锁。例如,如果有事务需要获取表A和表B的锁,所有事务都应该先获取表A的锁,再获取表B的锁。这样可以防止循环依赖导致的死锁。
- 减少锁的持有时间:尽量缩短事务持有锁的时间。在获取锁后尽快完成必要的操作,然后释放锁。例如,将事务中的操作尽可能精简,避免在事务中进行耗时的计算或外部资源访问。
- 使用较小的事务:将大事务拆分成多个小事务。小事务持有锁的时间相对较短,降低了死锁发生的概率。同时,即使发生死锁,回滚小事务的代价也相对较小。
- 设置合理的锁超时时间:可以通过设置
PRAGMA busy_timeout
来指定在获取锁时等待的最长时间。如果在超时时间内无法获取锁,事务会放弃并返回SQLITE_BUSY
错误。这样可以避免事务无限期等待锁,减少死锁的可能性。应用程序可以根据实际情况合理调整这个超时时间。