pg_dump报shared memory不足,300GB/39000表数据库备份求助
这个问题我之前帮不少用户解决过,尤其是针对超大规模表量的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:分批次备份(适合无法调整系统配置的场景)
如果受限于操作系统权限或共享内存无法调整,可以分批次备份,避免一次性锁定所有表:
- 先导出整个数据库的结构(不包含数据):
pg_dump -s -d your_database_name > schema_backup.sql - 按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:并行备份分散锁压力
使用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

