# F0001 — lock_file_exists

> PostgreSQL SQLSTATE F0001 的源码核验与诊断参考。
---

# F0001

## 速览 {#at-a-glance}

`F0001` 是启动时的所有权冲突。PostgreSQL 同时检查目标数据目录的 lock file 和共享内存身份；活跃所有者与崩溃留下的残留物是不同情况。

<!-- BEGIN SQLSTATE FACTS: generated by scripts/generate.py; do not edit -->

| 字段 | 值 |
| --- | --- |
| SQLSTATE | `F0001` |
| 条件名 | `lock_file_exists` |
| 状态 | `有效` |
| 已知存在于 | `7.4` |
| 锁定快照 | `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_FILE_EXISTS` |
| 别名 | `—` |

<!-- source facts: data/errcodes/F0001.json -->
<!-- END SQLSTATE FACTS -->

## 含义 {#meaning}

`CreateLockFile` 用 `O_EXCL` 原子创建锁文件。已有文件若包含 PID，会用 `kill(pid, 0)` 区分进程仍活跃还是已经消失；数据目录锁文件还会读取记录的共享内存标识并调用 `PGSharedMemoryIsInUse`。该辅助函数只把与目标 `DataDir` 关联的共享内存段视为相关，因为共享内存 ID 可能偶然重合。空锁文件是独立的 F0001 分支，可能表示另一个服务器正在启动，也可能是上次启动崩溃的残留。

SysV 共享内存启动路径也有同样边界：仍有进程附着或分析结果不确定的既有共享内存段报告仍在使用；与数据目录相关但无进程附着的共享内存段才可清理后重建。这些 guard 防止两个 postmaster 认领同一集群。

## 消息 {#messages}

- **FATAL**，SQLSTATE `F0001`：`lock file "%s" already exists`。
  - 数据目录提示：`Is another postgres (PID %d) running in data directory "%s"?`（编码所有者为 postmaster 时会使用对应提示文案）。
  - socket lock 变体会写 `using socket file "%s"`。
- **FATAL**，SQLSTATE `F0001`：`lock file "%s" is empty`。
  - 提示：`Either another server is starting, or the lock file is the remnant of a previous server startup crash.`
- **FATAL**，SQLSTATE `F0001`：`pre-existing shared memory block (key %lu, ID %lu) is still in use`。
  - 提示：`Terminate any old server processes associated with data directory "%s".`

其他锁文件 I/O 失败使用 `errcode_for_file_access()`，可能得到不同 SQLSTATE，不能都归入 `F0001`。

## 诊断 {#diagnosis}

确认精确 `PGDATA`、socket 目录、PID、启动时间、记录的 device/inode 身份、进程所有者和 postmaster 日志。`kill(pid, 0)` 成功，或失败 errno 既不是 `ESRCH`（进程不存在）也不是 `EPERM`（进程存在但调用者无权发送信号），会保持活跃进程分支。guard 将 `EPERM` 排除在活跃进程分支之外，是因为 `checkDataDir()` 以及 0600/0640 锁文件权限足以排除不同 UID 的进程作为竞争 postmaster；它只允许继续做身份和共享内存检查，并不授权直接删除锁文件。PID 消失或被视为不同 UID 候选后，还要检查数据目录共享内存 ID 及是否仍有孤儿后端附着，再考虑清理。空锁文件在源码中明确是歧义状态，不代表一定残留。

## 处理 {#response}

这是启动阶段的 **FATAL**，没有客户端事务可恢复；解决所有权冲突后启动服务器，再使用新连接。若另有 postmaster/后端存活，应按正常管理流程协调或停止。只有确认集群、进程身份和共享内存状态后，才能按文档处理陈旧锁文件。绝不能仅凭路径、PID 文本或数字 ID 删除锁文件/共享内存；所有者活跃时删除可能造成双主冲突（两个 postmaster 认领同一集群）和数据丢失。

## 版本 {#versions}

锁定目录从 7.4 记录此条件；固定启动与共享内存路径来自 PostgreSQL 18.6。本源码条目没有诱发进程、lock-file 或共享内存故障。

## 相关 {#related}

[`F0000`](../f0000/)、[`57P03`](../57p03/)、[`58P01`](../58p01/)

## 来源 {#sources}

[`src/backend/utils/init/miscinit.c#L1262-L1427`](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/utils/init/miscinit.c#L1262)

[`src/backend/port/sysv_shmem.c#L306-L335`](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/port/sysv_shmem.c#L306)

[`src/backend/port/sysv_shmem.c#L765-L835`](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/port/sysv_shmem.c#L765)

结构化[证据记录](../../data/evidence/f0001.json)保存活动/陈旧检查、固定 FATAL 消息和源码/运行边界。
