跳转到主要内容

55P03 — lock_not_available

PostgreSQL SQLSTATE 55P03 的完整来源与诊断条目。

55P03

速览

55P03 表示在当前等待策略下无法取得请求的锁。固定路径覆盖行锁、关系锁、LOCK TABLElock_timeout,以及无法取得关系锁时跳过对象的维护命令。

字段
SQLSTATE 55P03
条件名 lock_not_available
状态 有效
已知存在于 8.0.0
锁定快照 9.0.23, 9.1.24, 9.2.24, 9.3.25, 9.4.26, 9.5.25, 9.6.24, 10.23, 11.22, 12.22, 13.23, 14.24, 15.19, 16.15, 17.11, 18.6, 19beta3
ERRCODE_LOCK_NOT_AVAILABLE
别名

含义

行锁调用使用 LockWaitErrorConditionalXactLockTableWait()/ConditionalMultiXactIdWait(),立即报告 could not obtain lock on row in relation "%s"。关系锁和 LOCK TABLE 使用 ConditionalLockRelationOid(),报告关系对象变体。lock_timeout 是另一个 ERROR 路径,报 canceling statement due to lock timeout;它表示等待超过配置的 timeout,并不表示请求使用了 NOWAIT

VACUUM 和 ANALYZE 取得关系锁失败时也使用此 SQLSTATE,但它们的 ereport(elevel) 有意不提升为 ERROR:普通维护报告 WARNING,autovacuum 的 verbose 路径可能使用 LOG。命令会跳过该对象并继续,因此这类 warning 不等于事务已中止。

诊断

保留完整 primary message、severity、关系或行名、锁模式和语句。检查 pg_stat_activitypg_locks、阻塞 PID、事务时长,以及语句使用的是 NOWAITlock_timeout 还是维护命令。不要把 VACUUM/ANALYZE 跳过对象的 warning 当成 DML 失败。

已接受的行锁案例使用独立 blocker 和 autocommit contender。显式事务中的锁 ERROR 会使 session 进入 INERROR,直到 ROLLBACKROLLBACK TO SAVEPOINT;该案例的 autocommit contender 在失败后保持 IDLE

处理

协调或释放 blocker,或明确选择等待、timeout、skip 策略。显式事务中的 ERROR 后,先回滚整个事务或回到既有 savepoint,再发送 SQL,并核对已提交工作后重放。autocommit 下先改变阻塞或 timeout 条件,再按幂等规则重试语句。维护 WARNING/LOG 只需记录跳过的关系并稍后补做维护;命令没有中止事务时不要执行 ROLLBACK

实测诊断

选定注册表创建 blocker,在显式事务中持有 SELECT ... FOR UPDATE,并由 autocommit contender 发出 FOR UPDATE NOWAIT。PostgreSQL 18.6 与 10.21 均返回 ERROR / 55P03could not obtain lock on row in relation "nowait_rows";contender 保持 IDLE。blocker 回滚后,同一 contender 将 marker 更新为 repaired 并完成验证。

代表案例

以下 SQL 是带角色说明的注册表片段。setup 只执行一次,blocker 与 contender 必须使用不同会话;片段只覆盖行锁 NOWAIT,不覆盖 lock_timeout 或维护跳过分支。

-- setup(一个维护会话)
CREATE TABLE nowait_rows(id integer PRIMARY KEY, marker text NOT NULL);
INSERT INTO nowait_rows VALUES (1, 'seed');

-- blocker 会话:保持事务打开
BEGIN;
SELECT id FROM nowait_rows WHERE id = 1 FOR UPDATE;

-- contender 会话,开启 autocommit:这里触发 55P03
SELECT id FROM nowait_rows WHERE id = 1 FOR UPDATE NOWAIT;

-- blocker 会话
ROLLBACK;

-- 释放 blocker 后,在 contender 会话中修复并验证
UPDATE nowait_rows SET marker = 'repaired' WHERE id = 1 RETURNING marker;
SELECT marker FROM nowait_rows WHERE id = 1;

该案例只确认行锁机制、ERROR/IDLE 边界和修复步骤,不能据此断言每种锁模式或维护命令有相同 severity。

版本

锁定目录从 8.0.0 记录此条件;固定源码覆盖 PostgreSQL 18.6。已接受的运行观察来自 PostgreSQL 18.6 和 10.21。

55P024000157014

来源

src/backend/access/heap/heapam.c#L5178-5210

src/backend/catalog/namespace.c#L585-610

src/backend/tcop/postgres.c#L3420-3444

src/backend/commands/lockcmds.c#L130-145

src/backend/commands/vacuum.c#L835-880

结构化证据记录保存固定消息角色、维护 severity 以及已接受的运行产物。