本来只是一次普通的数据库重启,执行 pg_ctl restart 后却突然报错------
FATAL: pre-existing shared memory block is still in usepg_ctl: PID file "/data/pgdata/data/postmaster.pid" does not exist
数据库启动失败、PID文件丢失、共享内存冲突同时出现,看起来像是系统"坏掉了"。
如果你不了解 PostgreSQL 的进程机制和共享内存管理原理,很容易陷入反复重启、误删文件甚至误判故障的困境。
事实上,这类问题在 数据库异常关闭、服务器强制重启、或进程被 kill -9 杀死 后非常常见。
今天这篇文章,就结合一次真实排障过程,完整拆解:
-
为什么 PostgreSQL 会出现 共享内存冲突
-
PID 文件为什么会 突然消失
-
如何快速判断问题来源
-
DBA 标准处理步骤是什么
只需要 4个排障步骤,就能让数据库恢复正常启动。
下面我们一步一步还原整个排障过程。
01
问题描述 (Symptom)
在使用 pg_ctl restart 命令重启PostgreSQL数据库时,操作失败。
错误日志显示以下关键信息:
ps -ef | grep postgres
pg_ctl: PID file "/data/pgdata/data/postmaster.pid" does not exist
pg_ctl 工具报告说 postmaster.pid 文件不存在,这通常意味着数据库服务没有正常运行或在尝试启动前已经异常终止。
FATAL: pre-existing shared memory block (key 36815078, ID 4161551) is still in use
数据库启动进程在尝试分配共享内存时,发现一个已存在的、并且仍被占用的共享内存块。
这是导致启动失败的根本原因。
HINT: Terminate any old server processes associated with data directory "/data/pgdata/data".
日志提示建议终止与该数据目录相关的旧服务器进程。
02
原理分析 (Cause Analysis)
这个问题的根本原因在于 PostgreSQL进程异常终止。
在正常运行时,PostgreSQL的主进程(postmaster)会在数据目录下创建一个 postmaster.pid 文件,其中记录了主进程的ID(PID)以及其他信息,如共享内存段的ID。
同时,它会向操作系统申请一块共享内存,用于各后端进程之间的数据共享,例如shared_buffers(共享缓冲区)就位于这块内存中。
当数据库正常关闭时,主进程会执行以下清理操作:
1)释放它所申请的共享内存和信号量。
2)删除 postmaster.pid 文件。
然而,当数据库遭遇强制关机、操作系统崩溃、kill -9强制杀死进程等异常情况时,主进程没有机会执行正常的清理程序。
这会导致:
postmaster.pid 文件被删除或未来得及删除
在本次场景中,文件不存在,pg_ctl因此判断"服务未运行"。
共享内存段未被释放
操作系统内核中仍然保留着上次PostgreSQL运行时申请的共享内存段。
当您尝试重启PostgreSQL时,新的启动进程会:
1)检查postmaster.pid文件,发现它不存在,于是认为可以安全启动。
2)接着,它根据配置尝试向操作系统申请一块新的共享内存。
3)操作系统根据PostgreSQL计算出的key(在本例中是 36815078)发现,这个key对应的共享内存块(ID为 4161551)已经被占用了。
4)为了防止新旧进程同时操作一块内存区域导致数据严重损坏,新的PostgreSQL进程会拒绝启动,并抛出"pre-existing shared memory block is still in use"的致命错误。
03
实验验证 (Verification)
根据原理分析,我们需要验证系统中是否存在残留的PostgreSQL进程和共享内存段。
1
步骤一:检查残留的PostgreSQL进程
执行以下命令,查找是否还有与PostgreSQL相关的进程在运行。
通常,在异常崩溃后,主进程可能消失,但一些后端服务进程可能成为"孤儿"进程。
# 查看系统中的所有共享内存段
ipcs -m
# 为了方便定位,可以结合grep过滤
ipcs -m | grep postgres
2
步骤二:检查残留的共享内存段
根据错误日志中的 key 36815078,我们可以使用 ipcs 命令来查找对应的共享内存段。
# 使用 shmid 来删除共享内存段
ipcrm -m 4161551
预期结果
您应该能看到一个或多个共享内存段。请关注 shmid 和 key 列。
根据日志,您会找到一个 key 为 0x0231c0e6(36815078的十六进制表示)且 shmid 为 4161551 的条目。
这证实了共享内存段确实存在残留。
04
解决方案 (Solution)
警告
执行以下操作前,请确保您已经通过上述验证步骤确认了问题所在,并且当前没有正在对数据库进行重要操作的用户。
错误地清理共享内存可能导致正在运行的正常数据库实例损坏。
1
步骤一:清理残留的PostgreSQL进程
(如果存在)
如果在验证步骤中发现了残留进程,请使用 kill 命令将其终止。
建议首先尝试正常终止(kill -15),如果无效再使用强制终止(kill -9)。
# 替换 <PID> 为您找到的进程ID
kill -15 <PID>
# 如果上述命令无效,等待几秒后使用
kill -9 <PID>
2
步骤二:清理残留的共享内存段
这是解决问题的核心步骤。
使用 ipcrm 命令和从日志或ipcs命令中获取的共享内存ID (shmid) 来手动删除该内存段。
# 使用 shmid 来删除共享内存段
ipcrm -m 4161551
验证
执行命令后,再次运行 ipcs -m,确认ID为 4161551 的条目已经消失。
3
步骤三:清理残留的信号量(可选但推荐)
PostgreSQL同样使用信号量进行进程间通信。异常关闭也可能导致信号量残留。
可以使用 ipcs -s 查看,并使用 ipcrm -s 进行清理。
通常,清理共享内存后,数据库就能正常启动。
如果问题依旧,可以回来检查并清理信号量。
# 查看信号量
ipcs -s | grep postgres
# 如果发现残留,使用semid删除
# ipcrm -s <semid>
4
步骤四:重新启动PostgreSQL服务
现在,所有残留的资源都已被清理,您可以安全地启动PostgreSQL了。
[postgres@pgdb1 data]$ pg_ctl start -D /data/pgdata/data
# 或者使用您之前的restart命令
# [postgres@pgdb1 data]$ pg_ctl restart
预期结果
数据库应该能够顺利启动,pg_ctl 会报告 "server started"。
您可以检查日志文件以确认启动过程是否正常。
通过以上四个步骤------描述、分析、验证、解决------我们完整地处理了因异常关闭导致的PostgreSQL共享内存冲突问题,确保了数据库可以安全、可靠地恢复服务。
写在最后
PostgreSQL 启动失败,看似只是一个简单的报错,但背后往往涉及 操作系统资源管理、数据库进程机制以及共享内存控制。
很多时候,真正的问题并不在数据库本身,而是因为 异常关闭后系统资源没有被正确释放,导致新的实例无法正常启动。
在这次案例中,我们通过四个标准步骤完成了排障:
1)判断故障现象
2)分析 PostgreSQL 工作原理
3)验证系统残留资源
4)手动清理共享内存并恢复服务
掌握这一套排障思路后,你会发现类似的 PostgreSQL 启动问题其实都有规律可循。
对于 DBA 来说,比记住命令更重要的是理解背后的机制。
因为只有理解 数据库如何运行,才能在系统出现异常时快速定位问题、恢复服务。
如果你在工作中也遇到过类似的数据库故障,欢迎在评论区分享你的排障经历。
后续我也会继续整理更多 数据库真实故障案例与排障思路,帮助大家在生产环境中少踩坑、快定位。
#PostgreSQL #数据库故障 #DBA实战 #故障处理
作者介绍
大家好,我是刘峰,安丫科技创始人 & 数据库技术高级讲师,专注于 PostgreSQL、国产数据库运维与迁移、数据库性能优化 等方向。
作为 PG中国分会官方授权讲师、PostgreSQL ACE 讲师认证专家,我长期活跃在一线项目实战中,拥有 10年以上大型数据库管理与优化经验,曾深度参与电信、金融、政务等多个行业的数据库性能调优与迁移项目。
欢迎关注我,一起深入探索数据库的无限可能,技术交流不设限!
📌 觉得有收获的话,记得点赞、收藏、转发支持一下哦,别忘了关注我获取更多数据库干货~
安呀智数据坊|我们能做什么
无论你是业务系统的技术负责人,还是数据部门的第一响应人,我们都能为你提供可靠的支持:
- 数据库类型支持
Oracle / MySQL / PostgreSQL / SQL Server 等主流数据库
- 核心服务内容
性能优化 / 故障处理 / 数据迁移 / 备份恢复 / 版本升级 / 补丁管理
- 系统性支持
深度巡检 / 高可用架构设计 / 应用层兼容评估 / 运维工具集成
- 专项能力补充
定制课程培训 / 甲方团队辅导 / 复杂问题协作排查 / 紧急救援支持
📮 如果你有一张删不掉的表、一个跑不动的查询,或者一场说不清的升级风险,欢迎来找我们聊聊。