PG:child process was terminated by signal 7: Bus error

分析报错 V2.0


问题:PG初始化失败(Bus error)

触发条件:同时满足以下三点时,低于 v16 的 PostgreSQL 执行 initdb 会因 Bus error 失败:

  1. 节点启用 HugePages(大页内存)
  2. Kubernetes Pod 未声明 HugePages 请求
    # 缺失示例声明:
    resources:
      requests:
        hugepages-2Mi: "1Gi"
    
  3. (可能原因) 节点使用 cgroup v1(未完全验证)

根本原因
PG v16 前,initdb 强制使用 huge_pages=try(无视 postgresql.conf 中的 =off 配置),在未分配 HugePages 的环境下尝试申请大页内存,触发信号 SIGBUS (Bus error)。


解决方案

1. 升级 PostgreSQL(≥v16)
  • 推荐方案:v16+ 支持 initdb -c "huge_pages=off" 显式禁用大页。
  • 操作:调整初始化命令:
    initdb -D /data -c "huge_pages=off"
    
2. 节点禁用 HugePages
sysctl vm.nr_hugepages=0        # 临时禁用
echo "vm.nr_hugepages=0" >> /etc/sysctl.conf  # 永久生效
3. Kubernetes Pod 声明 HugePages 请求
resources:
  requests:
    hugepages-2Mi: "1Gi"  # 按需调整大小
  limits:
    hugepages-2Mi: "1Gi"
4. 修改模板配置(临时方案)
  • 编辑模板文件 $PGR007/share/postgresql.conf.sample,将 huge_pages 改为 off
    huge_pages = off
    

关键参考

  1. Huge Pages and Postgres in Containers | Crunchy Data Blog
  2. PostgreSQL BUG #17757
  3. Kubernetes HugePages 文档
  4. CrunchyData/postgres-operator Issue #3477
  5. docker-library/postgres Issue #451

总结建议

方案适用场景维护成本
升级 PG ≥v16长期部署,可修改初始化命令低 ★推荐
节点禁用 HugePages无需大页的通用节点
Pod 声明 HugePages需大页性能优化的场景
修改模板配置无法升级/临时修复高(需重建)

:若需保留 HugePages 性能优势,优先选择 方案3(声明请求);否则推荐 方案1(升级PG) 一劳永逸解决问题。



还原了 PostgreSQL 在 HugePages 场景下的 Bus error 根因,而且清晰比较了解决路径,适合直接作为团队内部参考文档或 SOP 指南。以下是我对这份笔记的几点优化建议与补充,仅供参考:


🧩 可补充要点(选填)

🔸 对 PG Operator 用户的指引建议

如果你使用的是 CrunchyData Operator、Zalando Patroni 等自动管理工具,可以补充一句:

如使用 Operator,请检查其 postgresql.conf 参数注入逻辑,确保 initdb 阶段可注入 huge_pages=off,或者通过自定义容器 Entrypoint 添加 -c huge_pages=off 参数。


🔸 临时排查技巧

加入一小节快速验证命令可帮助定位问题:

# 查看当前系统启用的大页数
cat /proc/meminfo | grep Huge

# 检查 THP 状态(如果启用了 Transparent HugePages,可能引发 mmap 行为变化)
cat /sys/kernel/mm/transparent_hugepage/enabled

🔸 v16 初始化变化链接(选填)

可以加上 PostgreSQL v16 提供 -c huge_pages=off 的新特性文档链接(补完性):


🏁 结语建议:

🧠 最佳实践建议:未来统一 PostgreSQL 初始化接口参数标准化(如 initdb -c 强制传参),结合集群模板一并纳管,避免节点层配置变动影响数据库初始化流程。


分析报错 V1.0

你提供的日志和 lscpu 信息非常关键,结合起来已经能明确诊断出 PostgreSQL 启动失败的根因:这是典型的 容器/系统环境对 POSIX 共享内存支持不足或不可用 问题。


🧨 结论:

PostgreSQL 在初始化阶段尝试使用 POSIX 共享内存(dynamic_shared_memory_type=posix)时,反复触发 Bus error (signal 7),这是由于系统内 /dev/shm 挂载异常、权限或支持缺失等问题导致。


✅ 立即解决方法:切换为 sysv 共享内存

PostgreSQL 支持将动态共享内存的实现方式切换为 System V,兼容性更强:

方法一:修改配置(推荐)

将 PostgreSQL 启动参数中的共享内存类型设置为 sysv

dynamic_shared_memory_type = sysv

如果你是通过 Patroni 启动的 PostgreSQL:

✅ Patroni 配置中加入:
postgresql:
  parameters:
    dynamic_shared_memory_type: sysv

然后重启 Pod 或容器。


方法二:手动初始化测试

你可以进入容器或主机,手动执行:

initdb -D /pgdata/data/postgres-test \
  --username=postgres \
  --no-password \
  --locale=C \
  --encoding=UTF8 \
  --data-checksums \
  --shared-buffers=256MB \
  --max-connections=20 \
  --dynamic-shared-memory=sysv

🔧 根因细节解析(适合深入了解)

你系统 CPU 是 Intel Xeon Gold 5320 x2(共104核),硬件没问题。问题来自操作系统或容器环境中以下方面:

🔸 1. /dev/shm 没挂载或容量不足

POSIX SHM 依赖 /dev/shm,如果该目录未正确挂载或容量只有几十 MB,会导致 mmap 失败并触发 Bus error

运行以下命令检查:

df -h /dev/shm
mount | grep shm
典型问题现象:
  • /dev/shm 只有 64MB → PostgreSQL 在分配 shared_buffers 或其他共享块时失败
  • /dev/shm 根本不存在(部分 Alpine、Slim 镜像)
  • 权限被 AppArmor、Seccomp 限制

🔸 2. 你的环境使用了容器(如 Kubernetes)

在 Kubernetes 中,/dev/shm 不是自动挂载,除非你指定了 emptyDir.medium: Memory。否则,POSIX SHM 不能正常使用。


🛠️ 根本解决(容器部署时建议加挂 /dev/shm)

✅ 在 Kubernetes 中挂载 /dev/shm

apiVersion: v1
kind: Pod
spec:
  containers:
    - name: postgres
      image: postgres:13
      volumeMounts:
        - mountPath: /dev/shm
          name: dshm
  volumes:
    - name: dshm
      emptyDir:
        medium: Memory
        sizeLimit: 1Gi

🧪 验证建议

请在容器内执行以下命令排查:

# 查看 /dev/shm 是否存在及大小
df -h /dev/shm
ls -ld /dev/shm

# 查看 POSIX SHM 支持
touch /dev/shm/test

如果这些命令失败、空间不足、或目录不存在,就证实了问题点。


✅ 总结与推荐操作

操作建议
短期临时解决dynamic_shared_memory_type 改为 sysv
长期稳定方案容器中挂载足够大的 /dev/shm(建议 >= 512Mi)
配置位置PostgreSQL postgresql.conf 或 Patroni YAML
避免镜像问题尽量使用 glibc 基础镜像(如 Debian/CentOS),避免 Alpine

是否需要我直接帮你生成一个带 sysv 配置的 Patroni YAML 模板?或者想继续分析 shm 空间挂载是否合理?

大页?

是的,PostgreSQL 报 Bus error (core dumped) 并反复失败于 dynamic_shared_memory_type=posix 初始化确实可能与宿主机开启了「大页内存(HugePages)」有关,特别是在以下场景中非常相关:


一、宿主机启用了 HugePages,对 POSIX SHM 有可能影响

大页内存(HugePages)简介:

  • Linux 默认使用 4KB 的内存页(page),而 HugePages 提供更大的页(通常是 2MB 或 1GB)。
  • 启用 HugePages 后,某些共享内存分配会默认尝试使用大页,如果大页内存不足或映射权限不正确,就可能导致 Bus error
  • PostgreSQL 的 shared_buffers 和动态共享内存段(dsm)都可能试图映射大页。

⚠️ 可能的冲突表现:

情况描述
宿主机启用了 HugePages/proc/sys/vm/nr_hugepages > 0,且 PostgreSQL 尝试用它
容器或用户权限不足没有权限 mmap 大页内存,导致 mmap() 失败
POSIX SHM 默认启用匿名大页(Transparent HugePages)某些 glibc/mmap 系统调用默认对 POSIX SHM 使用大页

最终结果就是触发:

Bus error (core dumped) -- signal 7

🔍 二、快速检查是否启用了 HugePages

在宿主机上执行:

cat /proc/meminfo | grep -i huge

样例输出(表示启用了 HugePages):

HugePages_Total:     512
HugePages_Free:      480
HugePages_Rsvd:       10
Hugepagesize:       2048 kB

还可以查看是否启用了 Transparent HugePages(THP)

cat /sys/kernel/mm/transparent_hugepage/enabled

输出中如果有 [always],则表示总是启用(推荐改为 never)。


🧪 验证:你系统是否因 HugePages 导致 PostgreSQL 崩溃?

可以尝试以下手动测试(在容器中或容器外):

postgres --boot -x0 -F \
  -c dynamic_shared_memory_type=posix \
  -c shared_buffers=128MB

如果继续 Bus error,改用:

postgres --boot -x0 -F \
  -c dynamic_shared_memory_type=sysv \
  -c shared_buffers=128MB

若此命令成功运行,几乎可以确认 POSIX SHM + HugePages = 出错点


三、解决方案

方法操作建议
✅ 推荐dynamic_shared_memory_type 改为 sysv,绕过 POSIX SHM
✅ 可选在宿主机禁用 Transparent HugePages
✅ 容器优化加挂 /dev/shm 且避免 glibc/mmap 自动使用大页
❌ 不推荐关闭 HugePages 整体功能(可能影响其他高性能服务如 Oracle、ElasticSearch)

禁用 Transparent HugePages 示例:

echo never > /sys/kernel/mm/transparent_hugepage/enabled

✅ PostgreSQL 中关闭大页内存方式

你还可以在 postgresql.conf 添加参数,避免大页使用:

huge_pages = off

也可以在 Patroni 配置中:

postgresql:
  parameters:
    huge_pages: off

注意:此参数不影响 shared_buffers 本身,但会禁用 PostgreSQL 使用 HugePages 的尝试,可能避免大页 mmap 出错。


✅ 总结

是否有关答案
和 HugePages 有关吗?✅ 是,特别是 POSIX SHM 配合 HugePages 会触发 Bus error
如何解决改用 sysv、禁用 huge_pages、禁用 THP、挂载 /dev/shm
优先顺序建议先改为 sysv,然后挂载 /dev/shm,最后才考虑禁用 HugePages(系统层)

如你需要我生成完整的 PostgreSQL+Patroni 配置模板,或排查是否受 /dev/shm 限制影响,也可以继续发我当前容器/POD 的 YAML 或挂载信息,我帮你快速排查。是否继续?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值