MST

星途 面试题库

面试题:PostgreSQL 锁机制下的死锁预防与检测

假设在 PostgreSQL 数据库中存在多个事务并发执行,可能会发生死锁情况。请描述 PostgreSQL 是如何检测死锁的,并且说明从应用程序设计角度,怎样预防死锁的发生,例如在事务的执行顺序和锁的获取策略方面该如何考虑。
50.2万 热度难度
数据库PostgreSQL

知识考点

AI 面试

面试题答案

一键面试

PostgreSQL 检测死锁的方式

  1. 等待图检测:PostgreSQL 使用等待图(Wait-For Graph,WFG)算法来检测死锁。等待图是一个有向图,其中节点表示事务,边表示一个事务等待另一个事务持有的锁。数据库系统定期检查这个等待图,当发现图中存在环时,就意味着发生了死锁。例如,事务 T1 等待事务 T2 持有的锁,事务 T2 又等待事务 T3 持有的锁,而事务 T3 等待事务 T1 持有的锁,这就形成了一个环,即死锁。

应用程序设计预防死锁的方法

事务执行顺序

  1. 按照固定顺序访问资源:如果多个事务需要访问相同的一组资源,应用程序应确保所有事务都按照相同的顺序访问这些资源。例如,在涉及多个表的事务中,所有事务都先访问表 A,再访问表 B,最后访问表 C。这样可以避免因不同事务以不同顺序获取锁而导致的死锁。
  2. 将大事务拆分为小事务:大事务持有锁的时间较长,增加了死锁的风险。将大事务拆分成多个小事务,每个小事务完成一部分独立的工作,减少锁的持有时间,降低死锁发生的可能性。例如,原本一个包含复杂业务逻辑涉及多个表更新的大事务,可以拆分成几个分别处理不同业务逻辑的小事务,按顺序执行。

锁的获取策略

  1. 尽量减少锁的持有时间:在事务中尽快获取锁,完成操作后立即释放锁。例如,在读取数据后如果不需要对数据进行修改,应尽快释放共享锁,避免长时间持有锁导致其他事务等待。
  2. 使用合理的锁粒度:根据业务需求选择合适的锁粒度。如果可能,尽量使用行级锁而不是表级锁。行级锁只锁定需要操作的行,对其他行的并发操作影响较小,相比表级锁能减少死锁的发生概率。例如,在只需要更新某一行数据时,使用行级锁而不是对整个表加锁。
  3. 设置合理的锁超时:为获取锁设置一个合理的超时时间。如果在超时时间内无法获取到锁,事务放弃获取锁并回滚。这样可以避免事务无限期等待锁,减少死锁发生后的处理成本。例如,设置获取锁的超时时间为 10 秒,如果 10 秒内没有获取到锁,事务回滚并可以选择稍后重试。