↑↓ 选择↵ 打开⌫ 切换范围完整搜索

PG.CENTER 连接 PostgreSQL 文档、百科与生态知识。由 Pigsty 维护。

Wiki / SQLSTATE

40P01 — deadlock_detected:检测到死锁

检测到死锁,事务因等待环被选为受害者中止。

英文手册覆盖始于 PostgreSQL 8.1. 来源历史与运行验证各自保留独立版本边界。

当前阅读 PG 18·选择有来源记录的版本

aliases
未知
class name
Transaction Rollback
condition name
deadlock_detected
lang
en
sqlstate
40P01

版本定义 PG 18

速览 {#at-a-glance}

40P01 是 PostgreSQL 类别 40 transaction_rollback 中的 deadlock_detected 条件。它表示锁管理器发现事务之间形成等待环,因此选择一个受害事务并中止它。

主报文是 deadlock detected。服务器可能附带动态构造的等待图 detail、提示查看服务器日志的 hint,以及说明被中断语句的上下文。进程 ID、事务 ID 和具体等待图都随运行变化;应按 SQLSTATE 分支并保存结构化字段,不要匹配这些动态值。

代表性案例先让两个会话分别持有相反的行锁,再用 threading.Barrier 放行两个交叉请求,同时由独立观察会话采样 pg_stat_activity 的 wait_event_type=Lock。观察会话不负责放行请求。一个会话收到 40P01 后事务为 INERROR;幸存会话完成操作,随后两个会话都回到 IDLE。新的事务按顺序取得两把行锁并提交完整重试。

运行 40P01-manual-boundary-final-20260909 在 PostgreSQL 18.6 和隔离的 PostgreSQL 10.21 上均通过。逐目标断言和结构化观察保存在公开证据 JSON中。

含义与触发路径 {#meaning}

死锁需要等待图中出现环。常见形式是会话 A 锁住第 1 行后请求第 2 行,同时会话 B 锁住第 2 行后请求第 1 行。PostgreSQL 的死锁检测器会在配置的 deadlock timeout 到期后检查锁图,DeadLockReport 随后报告该条件。

这个错误说明事务协调失败,不表示行数据损坏。受害事务的全部工作都会中止。另一个事务可能在检测器打破环后继续,但它成功完成并不意味着受害事务的预期工作已经应用。

40P01 不等于最终成功的锁等待,也不同于由 statement timeout 引起的 57014。本案例观察到的 pg_stat_activity 锁等待用于证明死锁准备顺序;服务器返回的 deadlock detected 才是最终条件。

报文与诊断 {#messages}

下面的调度是代表性操作。应在两个连接上分别执行会话 A 和 B;两个会话先各自持有一把行锁,随后由 barrier 放行交叉请求,独立观察会话在请求等待期间采样两个 backend。观察会话不是放行条件。

CREATE TABLE locks(id integer PRIMARY KEY, marker text NOT NULL);
INSERT INTO locks VALUES (1, 'seed-1'), (2, 'seed-2');

-- 会话 A:开始事务、设置 deadlock_timeout,并锁住 id = 1。
BEGIN;
SET deadlock_timeout = '100ms';
UPDATE locks SET marker = 'first-1' WHERE id = 1;

-- 会话 B:开始事务、设置 deadlock_timeout,并锁住 id = 2。
BEGIN;
SET deadlock_timeout = '100ms';
UPDATE locks SET marker = 'second-2' WHERE id = 2;

-- 明确的 barrier 让两个请求同时进入锁循环。
UPDATE locks SET marker = 'first-2' WHERE id = 2;
UPDATE locks SET marker = 'second-1' WHERE id = 1;

-- 受害事务必须 ROLLBACK;幸存事务可以 COMMIT。
ROLLBACK;
COMMIT;

-- 新的重试连接按同一顺序取得锁,并验证两行。
BEGIN;
UPDATE locks SET marker = 'retry-1' WHERE id = 1;
UPDATE locks SET marker = 'retry-2' WHERE id = 2;
COMMIT;
SELECT id, marker FROM locks ORDER BY id;

PostgreSQL 18.6 对受害事务返回的形状为:

SQLSTATE: 40P01
severity: ERROR
message_primary: deadlock detected
message_detail: Process <pid-a> waits for ShareLock on transaction <xid-b>; blocked by process <pid-b>.
Process <pid-b> waits for ShareLock on transaction <xid-a>; blocked by process <pid-a>.
message_hint: See server log for query details.
context: while updating tuple (0,2) in relation "locks"
source: deadlock.c / DeadLockReport / line 1138

PG10 运行得到相同的主报文和字段,但源码行号随版本变化。detail 来自实时等待图,因此此处用运行时占位符表示进程和事务标识。hint 并不保证客户端一定收到对应的服务器日志条目,它是在日志已配置时指向调查位置。

诊断 {#diagnosis}

记录 SQLSTATE、严重级别、主报文、detail、hint、上下文、失败语句、backend PID 和事务状态。在等待仍存在时检查 pg_stat_activity 及相关锁视图。有用的观察应包含 wait_event_type=Lock、等待事件、当前查询和参与的 PID;单纯 sleep 不能建立死锁证据。

应根据实际应用代码及所有访问同一行或 advisory lock 的路径整理加锁顺序,并检查触发器、外键、索引或后台 worker 是否取得了额外的锁。deadlock_timeout 只控制何时检测,调大它会改变检测延迟,不能消除等待环。

错误发生后,受害连接必须先 ROLLBACK,因为此时为 INERROR;幸存连接在提交前可能为 INTRANS。runner 验证了显式清理后两者都回到 IDLE,并在重试前读取了数据。

处理与修复 {#response}

回滚受害事务并释放其锁,再选择完整修复:

  • 让所有代码路径按一致顺序取得同一组锁,最好显式排序键值。
  • 缩短事务,不要在持有数据库锁时等待外部工作。
  • 只有在操作可重复且结果具备幂等语义时,才从头重试整个事务,包括读取和加锁。
  • 重试后验证已提交的业务结果;幸存事务的部分更新不能证明受害事务的工作成功。

本案例的修复按顺序锁定第 1 行和第 2 行,提交 retry-1、retry-2,并在连接为 IDLE 时读取两行。生产实现仍需有限的重试预算和应用级幂等键;单凭 SQLSTATE 不能判断重复操作是否安全。

版本与边界 {#versions}

目录在 PostgreSQL 7.4 的锁定定义中已观察到 40P01,并持续到 8.4.22 的 pre-9.0 定义;随后在列出的所有正式快照直到 PostgreSQL 18.6 以及 PostgreSQL 19 Beta 3 预览中存在。这是 definition_only 的存在边界,不是确切实现引入版本或运行时使用断言。9.0 头文件视图到 9.1 文本定义之间记录了类别标题变化;这只是目录观察,不是代码引入日期。扫描范围内条件行没有其他定义变化。

双会话案例在 PostgreSQL 18.6 和 10.21 上均通过。检测时点、锁类型和 detail 取决于工作负载与设置;本页采用 SQLSTATE 及事务回滚要求作为兼容边界,而不是固定的进程 ID detail。

相关 {#related}

40001 — serialization_failure 同样要求从新快照开始重试完整事务。57014 — query_canceled 表示取消,不表示锁环。23503 — foreign_key_violation 和 23505 — unique_violation 是可能出现在锁顺序需要复核的事务中的完整性条件。25P02 — in_failed_sql_transaction 是受害事务中止后出现的后续状态。

来源 {#sources}

结构化证据记录在公开证据 JSON中。所有源码记录固定到 PostgreSQL commit 724edf9bde9d356724ad384a2e196edc3c9f80f7;运行记录保留各目标的精确 ID 和结构化观察。

比较版本

SQLSTATE 证据与已记录的运行版本

cases · two_session_lock_cycle
{
  "assertions": [
    "One statement receives 40P01",
    "The victim transaction is rolled back",
    "The surviving session can finish with one coherent update per row",
    "A post-victim retry takes locks in order and commits the complete repair"
  ],
  "case_id": "two_session_lock_cycle",
  "cleanup": "Roll back workers and drop the case schema.",
  "has_snippet": true,
  "position": 0,
  "preconditions": [
    "Two sessions",
    "Two rows",
    "Both sessions acquire one row lock before attempting the other"
  ],
  "repair": "Keep lock order consistent; after rollback, retry the complete idempotent transaction in that order and verify its committed result.",
  "trigger": "Each session requests the row held by the other, using a barrier and observed lock waits.",
  "versions": [
    "10",
    "18"
  ]
}
claims · identity.class-and-condition
{
  "claim_id": "identity.class-and-condition",
  "limits": "Directory identity does not identify the lock graph or the selected victim.",
  "method": "Read the Class 40 section and 40P01 row in the frozen errcodes.txt snapshot.",
  "position": 0,
  "runtime": [],
  "sources": [
    "src.errcodes.18.6"
  ],
  "statement": "40P01 is the deadlock_detected condition in Class 40 transaction_rollback."
}
claims · mechanism.deadlock-report
{
  "claim_id": "mechanism.deadlock-report",
  "limits": "The detail contains live process and transaction identifiers and is not a fixed user-facing template.",
  "method": "Trace DeadLockReport and compare the primary message, dynamic detail, hint, and source location in the victim diagnostic.",
  "position": 1,
  "runtime": [],
  "sources": [
    "src.deadlock.18.6",
    "doc.protocol.18"
  ],
  "statement": "The deadlock detector reports deadlock detected with a dynamically assembled wait-graph detail and the hint See server log for query details."
}
claims · runtime.cycle-and-recovery
{
  "claim_id": "runtime.cycle-and-recovery",
  "limits": "The survivor's winner can differ by timing; the run proves the controlled cycle and recovery, not a universal victim-selection rule.",
  "method": "Use an explicit barrier, observe transactionid Lock waits through pg_stat_activity, then inspect worker diagnostics, transaction states, and surviving rows.",
  "position": 2,
  "runtime": [],
  "sources": [
    "doc.mvcc.18",
    "case-manifest.40P01",
    "runtime.40P01-manual-boundary-final-20260909.latest",
    "runtime.40P01-manual-boundary-final-20260909.pg10"
  ],
  "statement": "An explicit two-session lock cycle produced one 40P01 victim in INERROR, left one coherent survivor transaction, and allowed the victim to recover with ROLLBACK."
}
claims · runtime.complete-retry
{
  "claim_id": "runtime.complete-retry",
  "limits": "A fixed ordered update is a repair proof for this case; application retries still need complete business-operation and idempotency review.",
  "method": "Run the retry statements in primary-key order on a fresh transaction and assert IDLE plus both post-retry rows.",
  "position": 3,
  "runtime": [],
  "sources": [
    "doc.mvcc.18",
    "snippet-registry.40P01.final",
    "runtime.40P01-registry-final-20260909.latest",
    "runtime.40P01-registry-final-20260909.pg10",
    "runtime.40P01-manual-boundary-final-20260909.latest",
    "runtime.40P01-manual-boundary-final-20260909.pg10"
  ],
  "statement": "After the deadlock cleanup, an ordered retry transaction updated both rows, committed, and produced retry-1 and retry-2."
}
claims · versions.catalogue-boundary
{
  "claim_id": "versions.catalogue-boundary",
  "limits": "The first scanned release is a lower bound, not an asserted introduction version.",
  "method": "Read the manifest snapshots and definition references for the code.",
  "position": 4,
  "runtime": [],
  "sources": [
    "manifest.40P01"
  ],
  "statement": "The locked catalogue records 40P01 in every listed formal snapshot from 9.0.23 through 18.6 and in 19beta3; pre-9.0 history is not scanned."
}
messages · message.deadlock-report
{
  "limits": "The source passes the assembled client wait graph through errdetail_internal(\"%s\", clientbuf.data); process, transaction, relation, and tuple values vary by run.",
  "message_id": "message.deadlock-report",
  "path": "",
  "position": 0,
  "raw": {
    "detail_template": "%s",
    "detail_type": "dynamic wait graph",
    "hint_template": "See server log for query details.",
    "id": "message.deadlock-report",
    "limits": "The source passes the assembled client wait graph through errdetail_internal(\"%s\", clientbuf.data); process, transaction, relation, and tuple values vary by run.",
    "primary_template": "deadlock detected",
    "severity_source": "explicit ERROR",
    "sources": [
      "src.deadlock.18.6"
    ],
    "sqlstate": "40P01"
  },
  "severity": "explicit ERROR",
  "sources": [
    "src.deadlock.18.6"
  ],
  "templates": [
    {
      "kind": "primary",
      "literal": "deadlock detected",
      "position": 0,
      "role": "",
      "template": "deadlock detected"
    },
    {
      "kind": "detail",
      "literal": "",
      "position": 1,
      "role": "",
      "template": "%s"
    },
    {
      "kind": "hint",
      "literal": "See server log for query details.",
      "position": 2,
      "role": "",
      "template": "See server log for query details."
    }
  ]
}
runtimes · runtime.40P01-registry-final-20260909.latest · 18.6 (Homebrew) · passed
{
  "cases": [
    "two_session_lock_cycle"
  ],
  "limits": "",
  "position": 0,
  "raw": {
    "cases": [
      "two_session_lock_cycle"
    ],
    "id": "runtime.40P01-registry-final-20260909.latest",
    "observed": {
      "lock_wait": {
        "wait_event": "transactionid",
        "wait_event_type": "Lock"
      },
      "retry": {
        "rows": [
          [
            1,
            "retry-1"
          ],
          [
            2,
            "retry-2"
          ]
        ],
        "status": "IDLE"
      },
      "rows_before_retry": [
        [
          1,
          "first-1"
        ],
        [
          2,
          "first-2"
        ]
      ],
      "statuses": {
        "survivor": "IDLE",
        "victim_after_error": "INERROR",
        "victim_after_rollback": "IDLE"
      },
      "synchronization": "Both workers first held one row lock; a barrier then released the two cross-row requests, while an independent observer sampled the transactionid lock waits. The observer did not release the requests.",
      "victim": {
        "message_hint": "See server log for query details.",
        "message_primary": "deadlock detected",
        "severity": "ERROR",
        "source_file": "deadlock.c",
        "source_function": "DeadLockReport",
        "source_line": "1138",
        "sqlstate": "40P01",
        "worker": "second"
      }
    },
    "raw": "verify/results/40P01-registry-final-20260909/latest/raw.jsonl",
    "raw_sha256": "bdfda4fc40404195f34d3297cf71eebdd2146ea44bf91fc58484498455a5953d",
    "run_id": "40P01-registry-final-20260909",
    "server_version": "18.6 (Homebrew)",
    "server_version_num": 180006,
    "snippet_registry": {
      "path": "verify/cases/40P01/snippets.json",
      "sha256": "71a3377497dc2c1ba5b71c9ba81f71fc3cff975fcd245613ba2ddb82857c0591"
    },
    "status": "passed",
    "summary": "verify/results/40P01-registry-final-20260909/latest/summary.json",
    "summary_sha256": "693bc9cc5696cbb892eb12808a2b15db875c52aad5961410f59679df63566c07",
    "target": "latest"
  },
  "run_id": "40P01-registry-final-20260909",
  "runtime_id": "runtime.40P01-registry-final-20260909.latest",
  "server_version": "18.6 (Homebrew)",
  "status": "passed",
  "target": "latest"
}
runtimes · runtime.40P01-registry-final-20260909.pg10 · 10.21 (Debian 10.21-1.pgdg90+1) · passed
{
  "cases": [
    "two_session_lock_cycle"
  ],
  "limits": "",
  "position": 1,
  "raw": {
    "cases": [
      "two_session_lock_cycle"
    ],
    "id": "runtime.40P01-registry-final-20260909.pg10",
    "image": "postgres@sha256:b2baf8998630663d21370da06387c950e587071bdd307ee34e661cdcc7442bcc",
    "observed": {
      "lock_wait": {
        "wait_event": "transactionid",
        "wait_event_type": "Lock"
      },
      "retry": {
        "rows": [
          [
            1,
            "retry-1"
          ],
          [
            2,
            "retry-2"
          ]
        ],
        "status": "IDLE"
      },
      "rows_before_retry": [
        [
          1,
          "second-1"
        ],
        [
          2,
          "second-2"
        ]
      ],
      "statuses": {
        "survivor": "IDLE",
        "victim_after_error": "INERROR",
        "victim_after_rollback": "IDLE"
      },
      "synchronization": "Both workers first held one row lock; a barrier then released the two cross-row requests, while an independent observer sampled the transactionid lock waits. The observer did not release the requests.",
      "victim": {
        "message_hint": "See server log for query details.",
        "message_primary": "deadlock detected",
        "severity": "ERROR",
        "source_file": "deadlock.c",
        "source_function": "DeadLockReport",
        "source_line": "1146",
        "sqlstate": "40P01",
        "worker": "first"
      }
    },
    "raw": "verify/results/40P01-registry-final-20260909/pg10/raw.jsonl",
    "raw_sha256": "33e4c878282a503d074da04aaceb11f0aa5d0a245cac601562a5ea847cd45f63",
    "run_id": "40P01-registry-final-20260909",
    "server_version": "10.21 (Debian 10.21-1.pgdg90+1)",
    "server_version_num": 100021,
    "snippet_registry": {
      "path": "verify/cases/40P01/snippets.json",
      "sha256": "71a3377497dc2c1ba5b71c9ba81f71fc3cff975fcd245613ba2ddb82857c0591"
    },
    "status": "passed",
    "summary": "verify/results/40P01-registry-final-20260909/pg10/summary.json",
    "summary_sha256": "ff489619acc2047333c05a4d565a0ad4c993a762b8c4abca3fe684cd8928cf0c",
    "target": "pg10"
  },
  "run_id": "40P01-registry-final-20260909",
  "runtime_id": "runtime.40P01-registry-final-20260909.pg10",
  "server_version": "10.21 (Debian 10.21-1.pgdg90+1)",
  "status": "passed",
  "target": "pg10"
}
runtimes · runtime.40P01-manual-boundary-final-20260909.latest · 18.6 (Homebrew) · passed
{
  "cases": [
    "two_session_lock_cycle"
  ],
  "limits": "This run proves the registry BEGIN/COMMIT/ROLLBACK statements for both lock-cycle sessions and the ordered retry execute with autocommit=True; worker synchronization still uses barriers and observed lock waits.",
  "position": 2,
  "raw": {
    "cases": [
      "two_session_lock_cycle"
    ],
    "id": "runtime.40P01-manual-boundary-final-20260909.latest",
    "limits": "This run proves the registry BEGIN/COMMIT/ROLLBACK statements for both lock-cycle sessions and the ordered retry execute with autocommit=True; worker synchronization still uses barriers and observed lock waits.",
    "observed": {
      "connections_autocommit": {
        "first": true,
        "retry": true,
        "second": true
      },
      "retry": {
        "rows": [
          [
            1,
            "retry-1"
          ],
          [
            2,
            "retry-2"
          ]
        ],
        "status": "IDLE"
      },
      "transaction_control": "Registry BEGIN/COMMIT/ROLLBACK statements run with autocommit=True; no driver implicit BEGIN participates."
    },
    "raw": "verify/results/40P01-manual-boundary-final-20260909/latest/raw.jsonl",
    "raw_sha256": "562a80715a6dcaf4f14d99c54001799e05c3c52353d9e836ab88039f47ce2cb5",
    "run_id": "40P01-manual-boundary-final-20260909",
    "server_version": "18.6 (Homebrew)",
    "server_version_num": 180006,
    "snippet_registry": {
      "path": "verify/cases/40P01/snippets.json",
      "sha256": "71a3377497dc2c1ba5b71c9ba81f71fc3cff975fcd245613ba2ddb82857c0591"
    },
    "status": "passed",
    "summary": "verify/results/40P01-manual-boundary-final-20260909/latest/summary.json",
    "summary_sha256": "4d5b1401badd66f6b1c33040d7bbbcfbc68ac611c3a7f508cb29a57bc2d95594",
    "target": "latest"
  },
  "run_id": "40P01-manual-boundary-final-20260909",
  "runtime_id": "runtime.40P01-manual-boundary-final-20260909.latest",
  "server_version": "18.6 (Homebrew)",
  "status": "passed",
  "target": "latest"
}
runtimes · runtime.40P01-manual-boundary-final-20260909.pg10 · 10.21 (Debian 10.21-1.pgdg90+1) · passed
{
  "cases": [
    "two_session_lock_cycle"
  ],
  "limits": "This run proves the registry BEGIN/COMMIT/ROLLBACK statements for both lock-cycle sessions and the ordered retry execute with autocommit=True; worker synchronization still uses barriers and observed lock waits.",
  "position": 3,
  "raw": {
    "cases": [
      "two_session_lock_cycle"
    ],
    "id": "runtime.40P01-manual-boundary-final-20260909.pg10",
    "image": "postgres@sha256:b2baf8998630663d21370da06387c950e587071bdd307ee34e661cdcc7442bcc",
    "limits": "This run proves the registry BEGIN/COMMIT/ROLLBACK statements for both lock-cycle sessions and the ordered retry execute with autocommit=True; worker synchronization still uses barriers and observed lock waits.",
    "observed": {
      "connections_autocommit": {
        "first": true,
        "retry": true,
        "second": true
      },
      "retry": {
        "rows": [
          [
            1,
            "retry-1"
          ],
          [
            2,
            "retry-2"
          ]
        ],
        "status": "IDLE"
      },
      "transaction_control": "Registry BEGIN/COMMIT/ROLLBACK statements run with autocommit=True; no driver implicit BEGIN participates."
    },
    "raw": "verify/results/40P01-manual-boundary-final-20260909/pg10/raw.jsonl",
    "raw_sha256": "c2789c19f9106cf34a49fbfa791fbe0e23706f87e8d8a133abfb360165aa8ee1",
    "run_id": "40P01-manual-boundary-final-20260909",
    "server_version": "10.21 (Debian 10.21-1.pgdg90+1)",
    "server_version_num": 100021,
    "snippet_registry": {
      "path": "verify/cases/40P01/snippets.json",
      "sha256": "71a3377497dc2c1ba5b71c9ba81f71fc3cff975fcd245613ba2ddb82857c0591"
    },
    "status": "passed",
    "summary": "verify/results/40P01-manual-boundary-final-20260909/pg10/summary.json",
    "summary_sha256": "1aca5e77935f4066898c72332cb16f06c16f56ccd00414349f21a746d46f6ed8",
    "target": "pg10"
  },
  "run_id": "40P01-manual-boundary-final-20260909",
  "runtime_id": "runtime.40P01-manual-boundary-final-20260909.pg10",
  "server_version": "10.21 (Debian 10.21-1.pgdg90+1)",
  "status": "passed",
  "target": "pg10"
}
sources · src.errcodes.18.6
{
  "commit": "724edf9bde9d356724ad384a2e196edc3c9f80f7",
  "docs_url": "",
  "kind": "",
  "location": "lines 329-334",
  "path": "src/backend/utils/errcodes.txt",
  "position": 0,
  "sha256": "6e8de346643ba84aa3c9c6a73360acfc7b2dfb89162c06c08ce9bf5bcd5bbcba",
  "source_id": "src.errcodes.18.6",
  "tag": "REL_18_6",
  "url": "https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/utils/errcodes.txt"
}
sources · src.deadlock.18.6
{
  "commit": "724edf9bde9d356724ad384a2e196edc3c9f80f7",
  "docs_url": "",
  "kind": "",
  "location": "lines 1071-1138",
  "path": "src/backend/storage/lmgr/deadlock.c",
  "position": 1,
  "sha256": "f9931d72369a752e5fff5df3b5bfe5ffd47a3f65651522d27cf62f75fac0075f",
  "source_id": "src.deadlock.18.6",
  "tag": "REL_18_6",
  "url": "https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/storage/lmgr/deadlock.c#L1071-L1138"
}
sources · doc.mvcc.18
{
  "commit": "724edf9bde9d356724ad384a2e196edc3c9f80f7",
  "docs_url": "",
  "kind": "",
  "location": "serialization and deadlock failure handling",
  "path": "doc/src/sgml/mvcc.sgml",
  "position": 2,
  "sha256": "4b7bf77ee0af4b86052330ff2421d567df3604b75fe7d4f522bec84fdea87340",
  "source_id": "doc.mvcc.18",
  "tag": "PG18-docs",
  "url": "https://www.postgresql.org/docs/18/mvcc-serialization-failure-handling.html"
}
sources · doc.protocol.18
{
  "commit": "724edf9bde9d356724ad384a2e196edc3c9f80f7",
  "docs_url": "",
  "kind": "",
  "location": "ErrorResponse fields",
  "path": "doc/src/sgml/protocol.sgml",
  "position": 3,
  "sha256": "745339e07ebbc2bb67d98b258e25772ada644ef26011e3cd6b3fcbb435235f89",
  "source_id": "doc.protocol.18",
  "tag": "PG18-docs",
  "url": "https://www.postgresql.org/docs/18/protocol-error-fields.html"
}
sources · manifest.40P01
{
  "commit": "",
  "docs_url": "",
  "kind": "local_artifact",
  "location": "snapshots and definition_blobs entries for the 40P01 definition",
  "path": "sources/manifest.lock.json",
  "position": 4,
  "sha256": "1727a275f336988ff96b4f9990a4ca253080f73fc5d316e7def165c8cf3708a8",
  "source_id": "manifest.40P01",
  "tag": "",
  "url": "../sources/manifest.lock.json"
}
sources · case-manifest.40P01
{
  "commit": "",
  "docs_url": "",
  "kind": "local_artifact",
  "location": "two_session_lock_cycle",
  "path": "verify/cases/40P01/cases.json",
  "position": 5,
  "sha256": "85a8653680509a53f9d8fa9b08bafa3eeabe78553ef7d1f4e0aaf0ef7a1abe3d",
  "source_id": "case-manifest.40P01",
  "tag": "",
  "url": "../verify/cases/40P01/cases.json"
}
sources · snippet-registry.40P01.final
{
  "commit": "",
  "docs_url": "",
  "kind": "local_artifact",
  "location": "two_session_lock_cycle ordered SQL",
  "path": "verify/cases/40P01/snippets.json",
  "position": 6,
  "sha256": "71a3377497dc2c1ba5b71c9ba81f71fc3cff975fcd245613ba2ddb82857c0591",
  "source_id": "snippet-registry.40P01.final",
  "tag": "",
  "url": "../verify/cases/40P01/snippets.json"
}

来源引用

完整定义与证据 JSON

定义来源

center · PostgreSQL 18 · english-manuals:72247742d92f7f3aaf91240f5e22f29a345fd3f3acdbd0cbe853b5995f934d21

正文语言: zh-Hans · english-manuals:72247742d92f7f3aaf91240f5e22f29a345fd3f3acdbd0cbe853b5995f934d21