You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

pg_dump报shared memory不足,300GB/39000表数据库备份求助

解决PostgreSQL pg_dump时"out of shared memory"错误的方案

这个问题我之前帮不少用户解决过,尤其是针对超大规模表量的PostgreSQL备份场景——39000张表确实容易触发锁相关的共享内存不足问题,咱们一步步来拆解解决方案:

核心原因分析

pg_dump在备份时会启动一个事务,对所有要备份的关系(表、索引、序列、约束等)加ACCESS SHARE锁,确保备份期间数据不被破坏性修改。当表量达到39000张时,需要的锁数量远超常规场景,而你的PostgreSQL实例共享内存中分配的锁槽空间不足以容纳这么多锁,就会触发out of shared memory错误。

虽然你已经把max_locks_per_transaction设到了50000,但全局可用的锁槽总数是max_locks_per_transaction × (max_connections + max_prepared_transactions),如果操作系统的共享内存限制(比如shmmax)不足以支撑这么多锁槽的内存占用,或者锁槽总数仍不够覆盖所有表及关联对象,错误还是会发生。


解决方案1:调整锁与共享内存配置(推荐)

这是最彻底的解决方案,从根源上解决锁资源不足的问题:

1. 计算所需锁槽数

你的数据库有39000张表,加上每个表的索引、序列等关联对象,建议预留至少60000个锁槽(留足余量)。根据全局锁槽公式:

总锁槽数 = max_locks_per_transaction × (max_connections + max_prepared_transactions)

假设你的max_connections是默认的100,max_prepared_transactions为0,那么设置max_locks_per_transaction = 600就能得到60000个锁槽(600×100),完全覆盖需求,同时不会过度占用共享内存。

2. 调整PostgreSQL配置

编辑postgresql.conf文件,修改或添加以下参数:

max_locks_per_transaction = 600  # 根据计算结果调整
# 保持其他现有配置不变:
# shared_buffers = 4GB
# maintenance_work_mem = 1024MB
# work_mem = 10MB

3. 检查并调整操作系统共享内存参数

PostgreSQL的所有共享内存结构(包括锁槽、shared_buffers)都需要在操作系统允许的共享内存范围内。以Linux系统为例:

  • 查看当前共享内存限制:
    sysctl kernel.shmmax kernel.shmall
    
  • kernel.shmmax是单个共享内存段的最大大小,需要至少大于shared_buffers加上锁槽占用的内存(比如你的shared_buffers是4GB,锁槽60000个约占38MB,总需求约4.04GB)。
  • 临时调整(重启后失效):
    sysctl -w kernel.shmmax=4339118080  # 约4.04GB
    sysctl -w kernel.shmall=1062016     # 4.04GB ÷ 4KB每页
    
  • 永久调整(编辑/etc/sysctl.conf):
    添加以下内容后执行sysctl -p生效:
    kernel.shmmax = 4339118080
    kernel.shmall = 1062016
    

4. 重启PostgreSQL服务

修改配置后必须重启服务才能生效:

sudo systemctl restart postgresql

解决方案2:分批次备份(适合无法调整系统配置的场景)

如果受限于操作系统权限或共享内存无法调整,可以分批次备份,避免一次性锁定所有表:

  1. 先导出整个数据库的结构(不包含数据):
    pg_dump -s -d your_database_name > schema_backup.sql
    
  2. 按schema或表名前缀分批次导出数据:
    # 导出指定schema的所有表数据
    pg_dump -n your_schema_1 -d your_database_name > schema1_data.sql
    pg_dump -n your_schema_2 -d your_database_name > schema2_data.sql
    # 或者按表名前缀导出
    pg_dump -t "order_*" -d your_database_name > order_tables.sql
    
  3. 恢复时先执行结构备份,再依次执行各数据备份文件即可。

解决方案3:并行备份分散锁压力

使用pg_dump的-j(--jobs)参数开启并行备份,让多个进程同时备份不同的表,每个进程只需要锁定自己负责的表,从而减少单个事务的锁数量:

# 开启4个并行进程,使用tar格式备份
pg_dump -j 4 -d your_database_name -f backup.tar -F t

注意:

  • 并行备份需要使用支持并行的格式(tar或directory格式)。
  • 确保max_connections数值大于等于并行进程数,避免连接耗尽。
  • 监控系统CPU、内存和IO负载,避免资源过载。

关键注意事项

  • 所有配置调整后必须重启PostgreSQL才能生效。
  • 如果数据库处于活跃写入状态,分批次或并行备份可能存在数据不一致风险,建议在业务低峰期操作,或使用pg_basebackup做物理备份。
  • 调整共享内存参数时,不要盲目设置过大,避免浪费系统资源。

内容的提问来源于stack exchange,提问作者Sampath Addepalli

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 06:44:42