audit_log的advisory lock与UPDATE顺序引发的新死锁窗口
機械翻訳 / Machine-translated
機械翻訳 / Machine-translated
用于串行化防篡改哈希链的advisory lock会持续保持到事务提交。若在ads UPDATE之后立即插入审计INSERT,与另一个事务的行锁交叉时,便会触发40P01死锁。解决方法是将审计写入统一移至所有UPDATE之后执行。
用于将防篡改哈希链串行化为单链的advisory lock,会持续保持到事务提交为止。 audit_log的BEFORE INSERT触发器(migration 0003)为避免并发INSERT冲突,会获取pg_advisory_xact_lock(hashtext('audit_log')::bigint),并在该事务结束前始终持有。另一方面,portal投放的反映处理(applyPartnerDelivery)将已移出或重新加入投放对象的广告的审计记录,以"ads UPDATE → 审计INSERT(获取advisory lock)→ 下一个placement的ads UPDATE"的顺序,在每个placement中多次穿插执行。当该处理与运营界面的广告暂停操作(同样为"ads UPDATE → 审计INSERT"的同类处理)并发执行,且双方以各自先更新的行被对方后续请求的顺序运行时,就会形成如下循环:已获取advisory lock的一方等待对方的行锁,而对方则等待advisory lock的释放。PostgreSQL检测到此循环后,报告40P01(deadlock detected)并强制终止其中一方。解决方法是将审计INSERT的调用集中到所有目标行UPDATE执行完毕之后统一进行。
详细步骤说明、验证方法及常见问题,均汇总于原文。
→ audit_log的advisory lock与UPDATE顺序引发的新死锁窗口|Rebounder Tech Blog