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

解决PostgreSQL容器(含8万张子分区表)共享内存不足错误

分区表COUNT(*)触发共享内存不足的解决方案

对包含8万张子表的顶层分区表执行COUNT(*)时,PostgreSQL需要为每个子表加锁,当锁需求超出共享内存锁池容量时,就会抛出out of shared memory, you might need to increase max_locks_per_connection错误。以下是参数调整方法和计算逻辑:

核心参数与锁池容量计算

锁池的总容量由三个参数共同决定:

  • max_locks_per_transaction:控制每个连接的锁配额(单事务可突破此值,只要总锁池足够)
  • max_connections:数据库允许的最大并发连接数
  • max_prepared_transactions:最大预备事务数(未启用则设为0)

总锁槽数(即能同时容纳的锁数量)计算公式:

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

每个锁槽约占168字节,因此锁池内存占用为总锁槽数 * 168字节,当前你的--shm-size=64g完全能满足需求。

目标参数计算步骤

针对你的场景(单事务需访问8万张子表):

  1. 确定锁需求:按8万子表+20%冗余计算,需至少96000个锁槽
  2. 设定连接数:根据业务并发需求,保持max_connections=8或调整至20以内即可(连接数越少,所需max_locks_per_transaction越小)
  3. 计算max_locks_per_transaction:
    假设max_prepared_transactions=0,代入总锁槽数=100000(覆盖96000需求):
    max_locks_per_transaction = 100000 / 8 = 12500
    
    为留足余量,可向上取整为13000或15000。

关键注意事项

  • 配置生效:修改postgresql.conf后必须重启PostgreSQL,确保参数加载
  • 验证参数:执行以下SQL确认配置是否正确:
    SELECT name, setting FROM pg_settings WHERE name IN ('max_locks_per_transaction', 'max_connections', 'max_prepared_transactions');
    
  • 查询优化:全表COUNT(*)对8万子表效率极低,建议:
    • 若无需精确值,使用SELECT reltuples FROM pg_class WHERE relname='顶层表名';获取统计估算值
    • 按分区并行查询后手动汇总结果,避免单事务锁定所有子表

推荐配置

以下配置可覆盖你的锁需求:

max_connections = 8
max_prepared_transactions = 0
max_locks_per_transaction = 15000

总锁槽数=8*15000=120000,锁池内存占用约20MB,完全符合你的Docker资源配置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 22:50:53