PostgreSQL生产环境完整配置:性能调优、高可用主从与pgBouncer连接池实战
PostgreSQL是功能最完整的开源关系数据库,在Django、Ruby on Rails等现代Web框架中被广泛使用。本文针对香港VPS的实际硬件规格,给出PostgreSQL从安装到高可用的完整配置方案。
一、安装PostgreSQL 16
<code"># Ubuntu 22.04安装PostgreSQL 16 apt install -y postgresql-common /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh apt install -y postgresql-16 postgresql-contrib-16 # 验证安装 systemctl status postgresql pg_lsclusters
二、基础安全配置
<code"># 切换到postgres用户 sudo -u postgres psql -- 修改超级用户密码 ALTER USER postgres PASSWORD '强密码至少32位'; -- 创建应用专用用户(非超级用户) CREATE USER appuser WITH PASSWORD '应用用户密码'; CREATE DATABASE appdb OWNER appuser; GRANT ALL PRIVILEGES ON DATABASE appdb TO appuser; -- 最小权限:只授予必要权限 REVOKE ALL ON SCHEMA public FROM PUBLIC; GRANT USAGE ON SCHEMA public TO appuser; \q
<code"># /etc/postgresql/16/main/pg_hba.conf # 只允许本地和特定IP访问 # TYPE DATABASE USER ADDRESS METHOD local all postgres peer # 本地postgres用户 local all all scram-sha-256 host all all 127.0.0.1/32 scram-sha-256 host appdb appuser Web服务器内网IP/32 scram-sha-256 # 禁止所有其他来源 # (注释掉或删除其他host行)
三、性能调优(postgresql.conf)
<code"># 使用pgtune自动计算推荐值:https://pgtune.leopard.in.ua # 以下为4核8G内存,SSD磁盘,Web应用场景的参考值 # ===== 内存配置(最重要)===== shared_buffers = 2GB # 25%物理内存(关键:越大越好,到物理内存40%) effective_cache_size = 6GB # 75%物理内存(告诉优化器可用缓存大小,不实际分配) work_mem = 16MB # 每个排序/哈希操作的内存(并发高时适当降低) maintenance_work_mem = 512MB # VACUUM/CREATE INDEX等维护操作的内存 # ===== WAL(Write-Ahead Log)===== wal_buffers = 64MB # WAL缓冲区(通常1/32 shared_buffers) checkpoint_completion_target = 0.9 max_wal_size = 4GB min_wal_size = 1GB wal_compression = on # 压缩WAL(节省磁盘,轻微增加CPU) # ===== 连接与并发 ===== max_connections = 100 # 生产环境通常100~200(配合pgBouncer) superuser_reserved_connections = 3 # ===== 查询优化器 ===== default_statistics_target = 100 # 统计采样率(越高优化器决策越准确) random_page_cost = 1.1 # SSD磁盘设为1.1(HDD默认4.0) effective_io_concurrency = 200 # SSD并发I/O能力 # ===== 并行查询 ===== max_parallel_workers_per_gather = 2 max_parallel_workers = 4 max_parallel_maintenance_workers = 2 # ===== 日志 ===== log_min_duration_statement = 1000 # 记录超过1秒的慢查询(毫秒) log_checkpoints = on log_connections = off # 高并发时关闭,避免日志过多 log_temp_files = 0 # 记录所有临时文件(帮助识别work_mem不足) log_line_prefix = '%t [%p]: [%l-1] user=%u,db=%d,app=%a,client=%h ' # ===== 自动清理 ===== autovacuum = on autovacuum_max_workers = 3 autovacuum_naptime = 30s # 每30秒检查一次 autovacuum_vacuum_cost_delay = 2ms # SSD磁盘降低延迟 autovacuum_vacuum_scale_factor = 0.05 # 5%行变化触发VACUUM
<code"># 应用配置并重启 systemctl restart postgresql-16 # 验证配置 sudo -u postgres psql -c "SHOW shared_buffers;" sudo -u postgres psql -c "SHOW work_mem;"
四、主从流复制配置
主节点配置
<code"># postgresql.conf(主节点) wal_level = replica max_wal_senders = 5 # 最多5个从节点 wal_keep_size = 1GB # 保留足够的WAL供从节点追赶 synchronous_commit = on # 同步提交(强一致性,性能稍低) # 创建复制专用用户 sudo -u postgres psql -c " CREATE USER replicator REPLICATION LOGIN PASSWORD '复制用户密码'; " # pg_hba.conf添加从节点访问权限 echo "host replication replicator 从节点内网IP/32 scram-sha-256" >> /etc/postgresql/16/main/pg_hba.conf systemctl reload postgresql-16
从节点初始化
<code"># 在从节点上执行(先停止PostgreSQL)
systemctl stop postgresql-16
# 清空从节点数据目录(谨慎!)
rm -rf /var/lib/postgresql/16/main/*
# 从主节点拉取基础备份
sudo -u postgres pg_basebackup \
--host=主节点内网IP \
--username=replicator \
--pgdata=/var/lib/postgresql/16/main \
--wal-method=stream \
--progress \
--verbose
# 创建恢复配置
cat > /var/lib/postgresql/16/main/postgresql.auto.conf << EOF
primary_conninfo = 'host=主节点内网IP port=5432 user=replicator password=复制用户密码 sslmode=prefer'
promote_trigger_file = '/tmp/postgresql.trigger.5432'
EOF
# 标记为从节点
touch /var/lib/postgresql/16/main/standby.signal
# 启动从节点
systemctl start postgresql-16
# 在主节点验证复制状态
sudo -u postgres psql -c "SELECT * FROM pg_stat_replication;"五、pgBouncer连接池
Django/Rails应用的每个请求都会建立数据库连接,高并发时大量连接创建/销毁造成巨大开销。pgBouncer在应用和数据库之间维护连接池,显著提升性能。
<code"># 安装pgBouncer apt install pgbouncer -y
<code"># /etc/pgbouncer/pgbouncer.ini [databases] # 应用连接 pgbouncer:5432,pgbouncer转发到 localhost:5432 appdb = host=127.0.0.1 port=5432 dbname=appdb [pgbouncer] logfile = /var/log/postgresql/pgbouncer.log pidfile = /var/run/postgresql/pgbouncer.pid listen_addr = 127.0.0.1 listen_port = 5432 # 应用连接此端口(看起来像直连PG) auth_type = scram-sha-256 auth_file = /etc/pgbouncer/userlist.txt # 连接池模式 pool_mode = transaction # 事务级复用(Django推荐,会话变量不保持) # 连接数限制 max_client_conn = 1000 # 最多1000个客户端连接 default_pool_size = 25 # 每个数据库池的后端连接数 min_pool_size = 5 reserve_pool_size = 5 reserve_pool_timeout = 3 # 超时设置 server_idle_timeout = 600 # 后端空闲连接10分钟后关闭 client_idle_timeout = 0 # 客户端空闲连接不主动关闭 # 管理界面 admin_users = pgbouncer_admin stats_users = pgbouncer_stats
<code"># /etc/pgbouncer/userlist.txt(存储客户端密码) "appuser" "SCRAM-SHA-256$4096:盐值$加密密码" # 从PostgreSQL获取加密密码 sudo -u postgres psql -t -c "SELECT rolpassword FROM pg_authid WHERE rolname='appuser';"
<code"># 启动pgBouncer systemctl enable pgbouncer systemctl start pgbouncer # 查看连接池状态 psql -h 127.0.0.1 -p 5432 -U pgbouncer_admin pgbouncer -c "SHOW POOLS;" psql -h 127.0.0.1 -p 5432 -U pgbouncer_admin pgbouncer -c "SHOW STATS;"
六、慢查询分析
<code"># 开启pg_stat_statements扩展(查询统计)
sudo -u postgres psql -c "CREATE EXTENSION IF NOT EXISTS pg_stat_statements;"
# postgresql.conf添加
shared_preload_libraries = 'pg_stat_statements'
pg_stat_statements.track = all
pg_stat_statements.max = 10000
# 重启后查看最慢的10条查询
sudo -u postgres psql -c "
SELECT
substring(query, 1, 80) AS short_query,
round(total_exec_time::numeric, 2) AS total_ms,
calls,
round(mean_exec_time::numeric, 2) AS avg_ms,
round((100 * total_exec_time / sum(total_exec_time) OVER())::numeric, 2) AS pct
FROM pg_stat_statements
ORDER BY total_exec_time DESC
LIMIT 10;
"七、定期维护任务
<code">#!/bin/bash # /usr/local/bin/postgresql-maintenance.sh # 每周日凌晨3点执行 sudo -u postgres psql appdb << 'SQL' -- 更新统计信息(帮助查询优化器做出正确决策) ANALYZE VERBOSE; -- 清理死元组,回收空间 VACUUM (ANALYZE, VERBOSE); -- 重置慢查询统计(方便下周分析) SELECT pg_stat_statements_reset(); SQL echo "PostgreSQL维护完成:$(date)"
八、总结
PostgreSQL调优的核心是合理配置内存(shared_buffers + work_mem)和WAL,配合pgBouncer连接池应对高并发,主从流复制保障高可用。IDC.Net的香港VPS同账号内网互通,主从节点通过内网传输WAL,延迟极低,复制延迟通常在1ms以内,是部署PostgreSQL高可用集群的理想平台。
版权声明:
作者:后浪云
链接:https://idc.net/help/442877/
文章版权归作者所有,未经允许请勿转载。
THE END
