「 数据丢了、主库挂了、表膨胀了、连接被打满------做 PG 运维,这几个场景迟早会撞上。今天把备份恢复、流复制、膨胀治理、连接池这几块串起来讲,命令都能直接复制用。 」
一、逻辑备份:pg_dump 日常兜底
pg_dump 只备份单个库,不影响线上读写,适合每天定时全量某个库。
|-------------------|----------------------------------------------------------------------------|
| 场景 | 命令 |
| 自定义格式备份(建议,可并行恢复) | pg_dump -U postgres -h 127.0.0.1 -p 5432 -d mydb -F c -f /backup/mydb.dump |
| 纯 SQL 文本备份 | pg_dump -U postgres -d mydb -f /backup/mydb.sql |
| 只备份某张表 | pg_dump -U postgres -d mydb -t public.orders -f /backup/orders.sql |
| 恢复自定义格式 | pg_restore -U postgres -d mydb /backup/mydb.dump |
| 恢复 SQL 文本 | psql -U postgres -d mydb -f /backup/mydb.sql |
注意:pg_dump 不备份角色和表空间,要带全局对象用 pg_dumpall -U postgres -f /backup/globals.sql(角色、权限、表空间定义)。PGCA 考试常考 pg_dump 与 pg_dumpall 的边界。
二、物理备份 + PITR:误删数据也能回到时间点
逻辑备份只能回到"备份时刻",物理备份 + WAL 归档才能做时间点恢复(PITR),找回误删前的状态。
前提(主库 postgresql.conf):
|-----------------|---------------------|----------------|
| 参数 | 建议值 | 说明 |
| wal_level | replica | 必须,否则 WAL 信息不足 |
| archive_mode | on | 开启归档 |
| archive_command | 'cp %p /archive/%f' | 归档脚本,%p 源 %f 名 |
基础备份与恢复步骤:
|--------------|--------------------------------------------------------------------------------------------------------------------------------------|
| 场景 | 命令 |
| 基础备份(tar 压缩) | pg_basebackup -U repl -h primary -p 5432 -D /backup/base -Ft -Z 5 -P |
| 恢复时指定回放目标 | 在 postgresql.auto.conf 写 restore_command = 'cp /archive/%f %p' 和 recovery_target_time = '2026-08-28 10:00:00',并放 recovery.signal 后启动 |
| 确认已回到目标时间点 | 看日志 recovery complete,或 SELECT pg_is_in_recovery(); 返回 f |
关键:PITR 靠的是"基础备份 + 这段时间的 WAL",所以 archive_command 必须真的把 WAL 落盘成功,否则恢复链断。PGCE 考点常把"只做基础备份没开归档"设为错题。
三、流复制:主库挂了 standby 顶上
一主一从,主库写、从库可读,主挂了切从库继续服务。
主库准备(postgresql.conf):
|-----------------------|---------|
| 参数 | 值 |
| wal_level | replica |
| max_wal_senders | 10 |
| max_replication_slots | 10 |
建复制账号、拉从库:
|-----------------|---------------------------------------------------------------------------------------------------------|
| 场景 | 命令 |
| 建复制专用角色 | CREATE ROLE repl REPLICATION LOGIN PASSWORD 'StrongPwd2026'; |
| 拉全量并直接成 standby | pg_basebackup -U repl -h primary -p 5432 -D /data/pgdata_standby -Fp -X stream -P --write-recovery-conf |
-R 会自动在从库生成 standby.signal 和 primary_conninfo,拉起来就是备库,不用手改配置。
监控复制状态:
|-------------|-------------------------------------------------------------------------------------------------------------------|
| 场景 | 命令(在主库执行) |
| 看从库连接和延迟 | SELECT application_name, state, write_lag, flush_lag, replay_lag FROM pg_stat_replication; |
| 从库看接收状态 | SELECT * FROM pg_stat_wal_receiver; |
| 看回放落后多少秒 | SELECT now() - pg_last_xact_replay_timestamp() AS replay_lag; |
| 看落后字节数(WAL) | SELECT application_name, pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn) AS lag_bytes FROM pg_stat_replication; |
四、表膨胀治理:vacuum 不是万能药
PG 用 MVCC,UPDATE/DELETE 旧版本不立刻回收,dead tuple 多了表就膨胀、索引也跟着大。
|---------------------------|----------------------------------------------------------------------------------------------------|
| 场景 | 命令 |
| 整库清理 + 更新统计(先 \c mydb) | VACUUM (VERBOSE, ANALYZE); |
| 更省事:命令行直接对库做(不加 -f 就不会锁表) | vacuumdb -d mydb -v -z |
| 单表精准清理(VACUUM 跟表名不是库名) | VACUUM (VERBOSE, ANALYZE) public.orders; |
| 看哪些表死元组多 | SELECT schemaname, relname, n_dead_tup FROM pg_stat_user_tables ORDER BY n_dead_tup DESC LIMIT 20; |
| 单表调小自动清理阈值 | ALTER TABLE orders SET (autovacuum_vacuum_scale_factor = 0.05); |
⚠ VACUUM FULL 会锁表并重建,业务高峰期千万别跑,会卡死写入。膨胀严重优先调 autovacuum 参数(autovacuum_max_workers、autovacuum_naptime)让它自己慢慢收。PGCA 常考 VACUUM 与 VACUUM FULL 的区别------前者在线不锁表,后者排他锁。
五、连接池 pgBouncer:挡住连接风暴
应用直连 PG,max_connections 一撑满新连接就进不来。pgBouncer 在前面做连接复用,几百个应用连接复用几十个后端连接。
pgbouncer.ini 关键配置:
|-----------------|---------------------------------------------|----------|
| 配置项 | 值 | 说明 |
| databases 段 | mydb = host=127.0.0.1 port=5432 dbname=mydb | 后端真实库 |
| listen_port | 6432 | 应用连这个端口 |
| pool_mode | transaction | 事务级复用,最稳 |
| auth_type | md5 | 按需 |
常用运维:
|---------|--------------------------------------------|
| 场景 | 命令 |
| 应用改连池端口 | psql -h 127.0.0.1 -p 6432 -U appuser mydb |
| 看连接池占用 | SHOW POOLS; |
| 热加载配置 | kill -SIGHUP $(cat /var/run/pgbouncer.pid) |
pool_mode 三种:session(整个会话占用)、transaction(事务结束即还)、statement(每条语句还,有游标或带事务的语句会报错)。大多数 web 应用用 transaction 最稳。
六、执行计划与索引:慢查询先 EXPLAIN
别猜,先 EXPLAIN (ANALYZE, BUFFERS) 看真实执行。
|--------------|----------------------------------------------------------------------------------------|
| 场景 | 命令 |
| 看真实执行计划 | EXPLAIN (ANALYZE, BUFFERS) SELECT * FROM orders WHERE user_id = 123; |
| 线上建索引不锁表 | CREATE INDEX CONCURRENTLY idx_orders_user ON orders(user_id); |
| 重建大索引不锁表 | REINDEX INDEX CONCURRENTLY idx_orders_user; |
| 找从没被用过的索引 | SELECT schemaname, relname, indexrelname FROM pg_stat_user_indexes WHERE idx_scan = 0; |
| 统计信息过期导致走错计划 | ANALYZE orders; |
⚠ CREATE INDEX / REINDEX 不加 CONCURRENTLY 会锁表,大表在高峰期加索引直接卡业务。CONCURRENTLY 不能写在事务块里。
七、日常避坑清单
|------------------|------------------------------------------------------------|
| 坑 | 正确姿势 |
| fsync=off 提升性能 | 生产绝对不能关,掉电就丢数据 |
| 高峰期跑 VACUUM FULL | 改调 autovacuum,或低峰再操作 |
| 连接数不设上限猛涨 | 前面套 pgBouncer,控 max_connections |
| 长事务不提交 | 设 idle_in_transaction_session_timeout、statement_timeout 兜底 |
| WAL 归档失败不报警 | 监控归档目录和 pg_stat_archiver |

▲ 一图速查:核心命令汇总(建议收藏)
小结
备份恢复(pg_dump / pg_basebackup + PITR)、流复制高可用、膨胀治理、连接池、执行计划------这五块串起来,PG 生产环境大半问题都有抓手。命令都放进表格里,复制到终端就能用。先把备份和流复制这两块搭起来,比什么都重要。