标准答案

  1. 事务级锁使用 pg_advisory_xact_lock 或 pg_try_advisory_xact_lock,在事务提交或回滚时自动释放;会话级锁使用 pg_advisory_lock,在会话关闭前都可能保留。
  2. 锁键应由稳定的资源标识和命名空间组成,避免不同业务把同一个整数误当成同一资源;如果使用哈希,必须评估碰撞并保留可追踪的映射。
  3. 需要快速失败时使用 try 版本并设置业务超时,获取不到锁要返回明确的稍后重试、跳过或转异步结果,而不是让请求无限排队。
  4. advisory lock 只对遵守同一锁键约定的数据库会话有效,不能替代唯一约束、乐观锁、状态条件或跨系统 fencing token。
  5. 锁持有者执行外部 HTTP、等待用户输入或把会话级锁连接放回共享连接池,都会放大阻塞;持锁事务应短小、可观测并有故障处理路径。

题目解析

advisory lock 不会自动理解“订单”“租户”或“任务”这些业务概念,它只是数据库维护的一组锁标识。真正的正确性来自所有写入路径都使用同一个键,并且关键写入仍有约束或条件检查兜底。

事务级锁通常更容易治理,因为事务结束会自动释放;会话级锁适合跨多个事务协调,但更依赖连接生命周期。对于连接池,必须确保锁的持有者、归还时机和连接关闭策略是一致的。

它适合在同一个 PostgreSQL 数据库内做单任务执行、资源串行化或轻量 leader 协调,不适合直接当成跨数据库、跨区域或外部资源的租约。需要跨系统互斥时,还要设计租约过期、fencing 和下游校验。

常见误区

  • 误区:只要加 advisory lock 就能防止所有重复写入。改正:锁只能保护遵守约定的路径,唯一约束和状态条件仍应放在实际写入点。
  • 误区:用未经命名空间隔离的字符串哈希作为锁键。改正:为业务和资源类型分配稳定命名空间,并评估哈希碰撞和映射可追踪性。
  • 误区:会话级锁拿到后把连接放回连接池。改正:会话级锁会跟着连接继续存在,必须在同一连接上释放,或改用事务级锁。

作者信息