一、概述
1.1 背景介绍
PostgreSQL 17 是目前功能最完整的开源关系型数据库之一。相比 MySQL,它在复杂查询、JSON 支持、扩展性和标准 SQL 兼容性上有明显优势,但运维模型差异较大——进程架构、MVCC 实现、WAL 机制都与 MySQL 有本质区别。对于从 MySQL 迁移过来的 DBA,理解这些差异是避免踩坑的关键。
1.2 技术特点
- 多进程架构:每个连接对应一个独立的 backend 进程,连接数直接影响内存消耗,这是 PostgreSQL 必须使用连接池的根本原因
- MVCC 实现差异:PostgreSQL 将旧版本数据存储在堆表中(而非 undo log),导致需要 VACUUM 定期清理死元组
- WAL 机制:Write-Ahead Log 不仅用于崩溃恢复,还是流复制和逻辑复制的基础
1.3 适用场景
- 场景一:复杂业务查询,需要窗口函数、CTE、全文搜索、地理信息(PostGIS)
- 场景二:需要强 ACID 保证的金融、电商核心业务
- 场景三:从 MySQL 迁移,业务对 JSON 操作、数组类型有需求
1.4 环境要求
| 组件 |
版本要求 |
说明 |
| PostgreSQL |
17.x |
本文基于 PostgreSQL 17 |
| 操作系统 |
Ubuntu 22.04 / RHEL 9 |
推荐 LTS 版本 |
| 内存 |
16GB+ |
shared_buffers 建议为内存的 25% |
| 存储 |
SSD,独立数据盘 |
WAL 和数据分开存放可提升性能 |
二、详细步骤
2.1 核心架构理解
2.1.1 进程模型
PostgreSQL 采用多进程模型,主要进程包括:
postmaster(主进程)
├── backend process × N # 每个客户端连接对应一个,处理查询
├── autovacuum launcher # 自动清理调度器
├── autovacuum worker × N # 实际执行 VACUUM/ANALYZE
├── WAL writer # 将 WAL buffer 刷写到磁盘
├── checkpointer # 执行 checkpoint,将脏页写入数据文件
├── background writer # 后台将脏页写出,减轻 checkpoint 压力
└── stats collector # 收集统计信息
每个 backend 进程在连接建立时 fork 自 postmaster,独立占用内存。100 个连接 × 每进程约 5-10MB = 500MB~1GB 仅用于进程开销,这是为什么 max_connections 不能随意调大的原因。
2.1.2 MVCC 与死元组
PostgreSQL 的 MVCC 通过在堆表中保留旧版本行(dead tuple)实现。UPDATE 操作实际上是插入新行 + 标记旧行为死元组,DELETE 只标记行为死元组,不立即释放空间。
死元组积累会导致:
- 表膨胀(table bloat),占用大量磁盘空间
- 索引膨胀,查询性能下降
- Transaction ID Wraparound 风险(最严重,会导致数据库强制进入只读模式)
VACUUM 负责清理死元组,VACUUM FULL 会重写整张表(需要排他锁,生产慎用)。
2.2 关键配置参数
2.2.1 内存相关参数
# 文件路径:/etc/postgresql/17/main/postgresql.conf
# shared_buffers:PostgreSQL 自身缓存,建议为物理内存的 25%
# 16GB 内存 → 4GB
shared_buffers = 4GB
# effective_cache_size:告知查询优化器操作系统缓存大小,影响执行计划选择
# 建议为物理内存的 75%(shared_buffers + OS page cache)
effective_cache_size = 12GB
# work_mem:每个排序/哈希操作可用内存
# 注意:一个查询可能有多个排序节点,实际消耗 = work_mem × 并发查询数 × 节点数
# 保守设置:总内存 / (max_connections × 2)
work_mem = 64MB
# maintenance_work_mem:VACUUM、CREATE INDEX、ALTER TABLE 等维护操作可用内存
# 设大可加速 VACUUM 和索引创建
maintenance_work_mem = 512MB
# wal_buffers:WAL 缓冲区,-1 表示自动(shared_buffers 的 1/32,最大 64MB)
wal_buffers = 64MB
2.2.2 连接与并发
# max_connections:最大连接数
# 生产环境建议 100-200,配合 PgBouncer 连接池使用
max_connections = 200
# 预留给超级用户的连接数,防止普通连接耗尽时无法登录维护
superuser_reserved_connections = 5
2.2.3 WAL 与复制
# wal_level:WAL 记录级别
# minimal:最少,不支持复制
# replica:支持流复制(默认)
# logical:支持逻辑复制,开销略高
wal_level = replica
# checkpoint_completion_target:checkpoint 完成时间占 checkpoint 间隔的比例
# 0.9 表示在下次 checkpoint 前 90% 的时间内完成,平滑 I/O
checkpoint_completion_target = 0.9
# max_wal_size:触发 checkpoint 的 WAL 大小上限
# 写入密集型业务可适当调大,减少 checkpoint 频率
max_wal_size = 4GB
# min_wal_size:WAL 文件最小保留量
min_wal_size = 1GB
# synchronous_commit:事务提交是否等待 WAL 落盘
# on:最安全,等待 WAL 写入磁盘
# off:异步提交,性能提升 30-50%,但崩溃可能丢失最近几个事务
# local:本地落盘但不等待 standby 确认
synchronous_commit = on
2.3 自动清理(autovacuum)配置
# 开启自动清理(默认开启,不要关闭)
autovacuum = on
# autovacuum 工作进程数
autovacuum_max_workers = 5
# 触发 autovacuum 的死元组比例阈值
# 死元组数 > autovacuum_vacuum_threshold + autovacuum_vacuum_scale_factor × 表行数
autovacuum_vacuum_threshold = 50
autovacuum_vacuum_scale_factor = 0.02 # 2%,大表可在表级别单独设置更小的值
# 触发 autoanalyze 的阈值
autovacuum_analyze_threshold = 50
autovacuum_analyze_scale_factor = 0.01 # 1%
# autovacuum 每次操作后休眠时间(毫秒),控制 I/O 压力
autovacuum_vacuum_cost_delay = 2ms # 默认 2ms,I/O 压力大时可调大到 10ms
对于超大表(亿级行),autovacuum_vacuum_scale_factor = 0.02 意味着需要 200 万死元组才触发,可能导致表膨胀。建议在表级别单独配置:
-- 对大表单独设置更激进的 autovacuum 参数
ALTER TABLE orders SET (
autovacuum_vacuum_scale_factor = 0.005, -- 0.5%
autovacuum_analyze_scale_factor = 0.002, -- 0.2%
autovacuum_vacuum_cost_delay = 5 -- 5ms
);
三、示例代码和配置
3.1 备份策略
3.1.1 pg_dump 逻辑备份
# 备份单个数据库(自定义格式,支持并行恢复)
pg_dump -h 127.0.0.1 -U postgres -d mydb \
-F c \ # 自定义格式(custom format)
-Z 5 \ # 压缩级别 5
-j 4 \ # 并行 dump 4 个表(需要 -F d 目录格式)
-f /backup/mydb_$(date +%Y%m%d).dump
# 恢复
pg_restore -h 127.0.0.1 -U postgres -d mydb_restore \
-j 4 \ # 并行恢复
-F c \
/backup/mydb_20260101.dump
# 仅备份 schema(不含数据)
pg_dump -h 127.0.0.1 -U postgres -d mydb -s -f schema.sql
# 备份特定表
pg_dump -h 127.0.0.1 -U postgres -d mydb -t orders -t order_items -F c -f orders_backup.dump
3.1.2 pg_basebackup 物理备份
# 全量物理备份(适合大数据库,速度快)
pg_basebackup -h 127.0.0.1 -U replicator \
-D /backup/base_$(date +%Y%m%d) \
-F tar \ # tar 格式
-z \ # gzip 压缩
-P \ # 显示进度
-Xs \ # 流式传输 WAL(stream)
--checkpoint=fast
# 备份完成后目录结构:
# /backup/base_20260101/
# ├── base.tar.gz # 数据目录
# └── pg_wal.tar.gz # WAL 文件
3.1.3 PITR(时间点恢复)配置
# postgresql.conf(主库)
archive_mode = on
archive_command = ‘cp %p /archive/%f’ # 生产环境建议推送到对象存储
# archive_command = 'aws s3 cp %p s3://my-bucket/pg-archive/%f’
# 恢复到指定时间点(recovery.conf 或 postgresql.conf 中)
restore_command = ‘cp /archive/%f %p’
recovery_target_time = ‘2026-01-15 14:30:00’
recovery_target_action = ‘promote’ # 恢复完成后提升为主库
3.2 流复制配置
3.2.1 主库配置
# postgresql.conf
wal_level = replica
max_wal_senders = 5 # 最多 5 个 WAL sender 进程
wal_keep_size = 1GB # 保留至少 1GB WAL,防止 standby 落后太多
hot_standby = on # 允许 standby 接受只读查询
# pg_hba.conf(允许复制连接)
host replication replicator 192.168.1.0/24 scram-sha-256
-- 创建复制用户
CREATE USER replicator WITH REPLICATION ENCRYPTED PASSWORD ‘ReplicaPass123’;
3.2.2 从库配置
# 1. 使用 pg_basebackup 初始化从库
pg_basebackup -h 192.168.1.10 -U replicator \
-D /var/lib/postgresql/17/main \
-P -Xs -R # -R 自动生成 standby.signal 和连接配置
# 2. 检查生成的 postgresql.auto.conf
cat /var/lib/postgresql/17/main/postgresql.auto.conf
# primary_conninfo = ‘host=192.168.1.10 port=5432 user=replicator password=ReplicaPass123’
# 3. 启动从库
systemctl start postgresql@17-main
# 4. 验证复制状态(在主库执行)
psql -U postgres -c “SELECT client_addr, state, sent_lsn, write_lsn, flush_lsn, replay_lsn, sync_state FROM pg_stat_replication;”
3.3 EXPLAIN ANALYZE 输出解读
-- 示例查询
EXPLAIN (ANALYZE, BUFFERS, FORMAT TEXT)
SELECT o.id, o.created_at, u.name
FROM orders o
JOIN users u ON o.user_id = u.id
WHERE o.status = ‘pending’
AND o.created_at > NOW() - INTERVAL ‘7 days’
ORDER BY o.created_at DESC
LIMIT 100;
典型输出解读:
Limit (cost=1234.56..1234.81 rows=100 width=48) (actual time=45.123..45.234 rows=100 loops=1)
-> Sort (cost=1234.56..1237.06 rows=1000 width=48) (actual time=45.120..45.180 rows=100 loops=1)
Sort Key: o.created_at DESC
Sort Method: top-N heapsort Memory: 35kB
-> Hash Join (cost=500.00..1200.00 rows=1000 width=48) (actual time=12.345..44.567 rows=1000 loops=1)
Hash Cond: (o.user_id = u.id)
Buffers: shared hit=850 read=150 -- hit: 从缓存读,read: 从磁盘读
-> Index Scan using idx_orders_status_created on orders o
Index Cond: ((status = ‘pending’) AND (created_at > ...))
Rows Removed by Filter: 50
-> Hash (cost=300.00..300.00 rows=10000 width=20) (actual time=8.000..8.000 rows=10000 loops=1)
Buckets: 16384 Batches: 1 Memory Usage: 625kB
-> Seq Scan on users u (cost=0.00..300.00 rows=10000 width=20)
关键指标:
cost=估算启动成本..估算总成本:优化器估算值,与 actual time 差距大说明统计信息过时
Buffers: shared hit=X read=Y:hit 多说明缓存命中好,read 多说明需要磁盘 I/O
Rows Removed by Filter:过滤掉的行数多说明索引选择性差或缺少合适索引
Seq Scan:全表扫描,大表出现时需要检查是否缺索引或统计信息不准
四、最佳实践和注意事项
4.1 最佳实践
4.1.1 性能优化
-
必须使用连接池:PgBouncer 是生产标配,transaction 模式下可将 1000 个应用连接复用为 20 个数据库连接
# pgbouncer.ini 核心配置
[databases]
mydb = host=127.0.0.1 port=5432 dbname=mydb
[pgbouncer]
pool_mode = transaction # transaction 模式,连接复用率最高
max_client_conn = 1000 # 最大客户端连接数
default_pool_size = 20 # 每个数据库的连接池大小
min_pool_size = 5
reserve_pool_size = 5 # 紧急预留连接数
server_idle_timeout = 600 # 空闲连接超时(秒)
-
索引策略:
-- 复合索引列顺序:等值查询列在前,范围查询列在后
CREATE INDEX idx_orders_user_status_created
ON orders (user_id, status, created_at DESC);
-- 部分索引:只索引常用子集,减小索引体积
CREATE INDEX idx_orders_pending
ON orders (created_at DESC)
WHERE status = ‘pending’;
-- 并发创建索引,不锁表(生产环境必用)
CREATE INDEX CONCURRENTLY idx_orders_new ON orders (user_id);
-
定期更新统计信息:
-- 手动触发 ANALYZE(不锁表)
ANALYZE orders;
-- 查看统计信息最后更新时间
SELECT schemaname, tablename, last_vacuum, last_autovacuum,
last_analyze, last_autoanalyze, n_dead_tup, n_live_tup
FROM pg_stat_user_tables
ORDER BY n_dead_tup DESC;
4.1.2 安全加固
-- 最小权限原则
CREATE ROLE app_readonly;
GRANT CONNECT ON DATABASE mydb TO app_readonly;
GRANT USAGE ON SCHEMA public TO app_readonly;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO app_readonly;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO app_readonly;
CREATE ROLE app_readwrite;
GRANT app_readonly TO app_readwrite;
GRANT INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO app_readwrite;
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO app_readwrite;
# pg_hba.conf:限制连接来源
# 禁止 trust 认证,强制使用 scram-sha-256
local all postgres peer
local all all scram-sha-256
host all all 127.0.0.1/32 scram-sha-256
host all all 192.168.1.0/24 scram-sha-256
host all all 0.0.0.0/0 reject
4.1.3 高可用配置
流复制 + Patroni 是目前最主流的 PostgreSQL HA 方案:
# patroni.yml 核心配置
scope: postgres-cluster
name: pg-node1
restapi:
listen: 0.0.0.0:8008
connect_address: 192.168.1.10:8008
etcd3:
hosts: 192.168.1.20:2379,192.168.1.21:2379,192.168.1.22:2379
bootstrap:
dcs:
ttl: 30
loop_wait: 10
retry_timeout: 10
maximum_lag_on_failover: 1048576 # 1MB,超过此 lag 不参与选主
postgresql:
listen: 0.0.0.0:5432
connect_address: 192.168.1.10:5432
parameters:
max_connections: 200
shared_buffers: 4GB
wal_level: replica
hot_standby: on
4.2 注意事项
4.2.1 与 MySQL 的关键差异
| 特性 |
PostgreSQL 17 |
MySQL 8.x |
注意事项 |
| 自增主键 |
SERIAL / GENERATED ALWAYS AS IDENTITY |
AUTO_INCREMENT |
PG 推荐用 IDENTITY,SERIAL 是旧语法 |
| 字符串大小写 |
默认区分大小写 |
默认不区分 |
迁移时注意 COLLATION 设置 |
| UPSERT |
INSERT ... ON CONFLICT DO UPDATE |
INSERT ... ON DUPLICATE KEY UPDATE |
语法不同 |
| 全文索引 |
内置 tsvector/tsquery |
需要 FULLTEXT 索引 |
PG 全文搜索功能更强 |
| JSON |
json/jsonb(jsonb 支持索引) |
JSON 类型 |
PG jsonb 性能更好 |
| 表分区 |
声明式分区(PG 10+) |
分区表 |
语法相似但细节不同 |
| 连接数 |
每连接一个进程,开销大 |
线程模型,开销小 |
PG 必须用连接池 |
4.2.2 常见错误
| 错误现象 |
原因分析 |
解决方案 |
FATAL: remaining connection slots are reserved |
连接数达到 max_connections |
检查连接泄漏,部署 PgBouncer |
ERROR: could not serialize access due to concurrent update |
序列化隔离级别下的冲突 |
应用层重试逻辑,或降低隔离级别 |
WARNING: database “mydb” must be vacuumed within N transactions |
接近 Transaction ID Wraparound |
立即手动执行 VACUUM FREEZE |
| 查询突然变慢(执行计划改变) |
统计信息过时,优化器选错执行计划 |
ANALYZE table_name,或 SET enable_seqscan = off 临时调试 |
| 表空间持续增长 |
autovacuum 未及时清理死元组 |
检查 autovacuum 日志,调整 autovacuum_vacuum_scale_factor |
五、故障排查和监控
5.1 故障排查
5.1.1 日志查看
# 查看 PostgreSQL 日志
tail -f /var/log/postgresql/postgresql-17-main.log
# 开启慢查询日志(postgresql.conf)
log_min_duration_statement = 1000 # 记录超过 1 秒的查询(毫秒)
log_line_prefix = ‘%t [%p]: [%l-1] user=%u,db=%d,app=%a,client=%h ’
log_checkpoints = on
log_connections = off # 高并发下不建议开启,日志量太大
log_lock_waits = on # 记录锁等待
deadlock_timeout = 1s # 死锁检测超时
5.1.2 常见问题排查
问题一:锁等待和死锁
-- 查看当前锁等待情况
SELECT
blocked.pid AS blocked_pid,
blocked.query AS blocked_query,
blocking.pid AS blocking_pid,
blocking.query AS blocking_query,
blocked.wait_event_type,
blocked.wait_event
FROM pg_stat_activity blocked
JOIN pg_stat_activity blocking
ON blocking.pid = ANY(pg_blocking_pids(blocked.pid))
WHERE blocked.cardinality(pg_blocking_pids(blocked.pid)) > 0;
-- 终止阻塞进程(先尝试 pg_cancel_backend,不行再 pg_terminate_backend)
SELECT pg_cancel_backend(pid); -- 取消当前查询,保留连接
SELECT pg_terminate_backend(pid); -- 终止连接
问题二:表膨胀检查
-- 查看表膨胀情况
SELECT
schemaname,
tablename,
pg_size_pretty(pg_total_relation_size(schemaname||‘.’||tablename)) AS total_size,
n_dead_tup,
n_live_tup,
round(n_dead_tup::numeric / NULLIF(n_live_tup + n_dead_tup, 0) * 100, 2) AS dead_ratio
FROM pg_stat_user_tables
WHERE n_dead_tup > 10000
ORDER BY n_dead_tup DESC
LIMIT 20;
问题三:长事务
-- 查找运行超过 5 分钟的事务
SELECT pid, usename, application_name, state,
now() - xact_start AS duration,
left(query, 100) AS query
FROM pg_stat_activity
WHERE xact_start IS NOT NULL
AND now() - xact_start > INTERVAL ‘5 minutes’
ORDER BY duration DESC;
5.2 性能监控
5.2.1 关键指标监控
# 数据库整体状态
psql -U postgres -c “
SELECT datname,
numbackends AS connections,
xact_commit AS commits,
xact_rollback AS rollbacks,
blks_hit AS cache_hits,
blks_read AS disk_reads,
round(blks_hit::numeric / NULLIF(blks_hit + blks_read, 0) * 100, 2) AS cache_hit_ratio,
deadlocks,
temp_files,
pg_size_pretty(temp_bytes) AS temp_size
FROM pg_stat_database
WHERE datname NOT IN (‘template0’, ‘template1’, ‘postgres’);”
5.2.2 监控指标说明
| 指标名称 |
正常范围 |
告警阈值 |
说明 |
| 缓存命中率 |
> 99% |
< 95% |
blks_hit / (blks_hit + blks_read) |
| 连接数 |
< max_connections × 80% |
> 90% |
接近上限时需扩容连接池 |
| 死锁数 |
0 |
> 0/分钟 |
持续出现死锁需排查业务逻辑 |
| 复制延迟 |
< 1MB |
> 100MB |
pg_stat_replication 中的 lag |
| 死元组比例 |
< 10% |
> 20% |
需要检查 autovacuum 是否正常工作 |
| 长事务时长 |
< 1分钟 |
> 5分钟 |
长事务阻塞 autovacuum 和 DDL |
5.2.3 Prometheus 监控规则
# postgres_alerts.yml
groups:
- name: postgresql
rules:
- alert: PostgreSQLCacheHitRateLow
expr: |
rate(pg_stat_database_blks_hit[5m]) /
(rate(pg_stat_database_blks_hit[5m]) + rate(pg_stat_database_blks_read[5m])) < 0.95
for: 10m
labels:
severity: warning
annotations:
summary: “PostgreSQL 缓存命中率低于 95%: {{ $value | humanizePercentage }}”
- alert: PostgreSQLReplicationLag
expr: pg_replication_lag > 300
for: 2m
labels:
severity: critical
annotations:
summary: “PostgreSQL 复制延迟超过 5 分钟: {{ $value }}s”
- alert: PostgreSQLDeadlocks
expr: rate(pg_stat_database_deadlocks[5m]) > 0
for: 1m
labels:
severity: warning
annotations:
summary: “PostgreSQL 检测到死锁”
5.3 备份与恢复
5.3.1 自动备份脚本
#!/bin/bash
# 文件名:pg_backup.sh
# 功能:PostgreSQL 每日全量备份 + WAL 归档
PGHOST=“127.0.0.1”
PGUSER=“postgres”
BACKUP_DIR=“/data/backup/postgresql”
DATE=$(date +%Y%m%d_%H%M%S)
RETENTION_DAYS=7
mkdir -p “$BACKUP_DIR”
# 全量物理备份
pg_basebackup -h “$PGHOST” -U replicator \
-D “$BACKUP_DIR/base_$DATE” \
-F tar -z -P -Xs \
--checkpoint=fast
if [ $? -eq 0 ]; then
echo “备份成功:$BACKUP_DIR/base_$DATE”
# 清理旧备份
find “$BACKUP_DIR” -maxdepth 1 -name “base_*” -mtime +$RETENTION_DAYS -exec rm -rf {} \;
else
echo “备份失败!” >&2
exit 1
fi
5.3.2 恢复流程
- 停止服务:
systemctl stop postgresql@17-main
- 清空数据目录:
rm -rf /var/lib/postgresql/17/main/*
- 解压备份:
tar -xzf base_20260101_120000/base.tar.gz -C /var/lib/postgresql/17/main/
- 配置恢复参数:在
postgresql.conf 中设置 restore_command 和 recovery_target_time
- 创建恢复信号文件:
touch /var/lib/postgresql/17/main/recovery.signal
- 启动服务:
systemctl start postgresql@17-main,观察日志确认恢复进度
六、总结
6.1 技术要点回顾
- ✅ 连接池是必选项:PostgreSQL 多进程模型决定了 max_connections 不能无限增大,PgBouncer transaction 模式是生产标配
- ✅ VACUUM 不可忽视:死元组积累会导致表膨胀和 Transaction ID Wraparound,大表需要单独调整 autovacuum 参数
- ✅ shared_buffers 是关键:设置为物理内存 25%,
effective_cache_size 设置为 75%,影响查询优化器决策
- ✅ 流复制 + Patroni:生产 HA 方案首选,自动故障转移,避免手动干预
6.2 进阶学习方向
- 逻辑复制与 CDC:
wal_level = logical 支持跨版本复制和数据同步,适合数据库迁移和实时数据管道
- 实践建议:结合 Debezium 实现 PostgreSQL → Kafka 的 CDC 数据流
- 分区表:声明式分区(范围分区、列表分区、哈希分区)管理超大表
- 实践建议:时序数据按月分区,配合 pg_partman 自动管理分区生命周期
- PostGIS 扩展:地理信息处理,支持空间索引和地理查询
6.3 参考资料
- PostgreSQL 17 官方文档 - 权威参考
- PgBouncer 文档 - 连接池配置
- Patroni 文档 - HA 方案
- pg_activity - 类似 top 的实时监控工具
通过对 PostgreSQL 17 的进程模型、关键配置、备份恢复策略和性能调优要点的系统梳理,希望这篇文章能帮助你快速上手并解决日常运维中的常见问题。记住,理解其独特的架构是避免踩坑的第一步。如果你在实践过程中遇到更多关于数据库的复杂场景,欢迎到云栈社区与更多同行交流经验。
附录
A. 命令速查表
psql -U postgres -c “SELECT version();” # 查看版本
psql -U postgres -c “SELECT pg_size_pretty(pg_database_size(‘mydb’));” # 数据库大小
psql -U postgres -c “SELECT * FROM pg_stat_activity;” # 当前连接
psql -U postgres -c “SELECT * FROM pg_stat_replication;” # 复制状态
psql -U postgres -c “VACUUM ANALYZE orders;” # 清理并更新统计
psql -U postgres -c “VACUUM FREEZE orders;” # 强制冻结(防 wraparound)
pg_dump -Fc -d mydb -f backup.dump # 逻辑备份
pg_restore -j 4 -d mydb backup.dump # 并行恢复
pg_basebackup -D /backup -Xs -P -R # 物理备份
B. 配置参数详解
| 参数 |
默认值 |
推荐值(16GB内存) |
说明 |
shared_buffers |
128MB |
4GB |
PostgreSQL 缓冲池 |
work_mem |
4MB |
64MB |
排序/哈希操作内存 |
maintenance_work_mem |
64MB |
512MB |
维护操作内存 |
effective_cache_size |
4GB |
12GB |
优化器估算可用缓存 |
max_connections |
100 |
200 |
配合连接池使用 |
checkpoint_completion_target |
0.9 |
0.9 |
checkpoint I/O 平滑 |
max_wal_size |
1GB |
4GB |
写密集型业务调大 |
C. 术语表
| 术语 |
英文 |
解释 |
| 死元组 |
Dead Tuple |
UPDATE/DELETE 后留在堆表中的旧版本行,需要 VACUUM 清理 |
| 检查点 |
Checkpoint |
将内存中的脏页批量写入磁盘的操作,保证崩溃恢复点 |
| 预写日志 |
Write-Ahead Log (WAL) |
所有数据变更先写日志再写数据,保证持久性 |
| 事务ID回卷 |
Transaction ID Wraparound |
32位事务ID耗尽后回绕,可能导致数据可见性错误 |
| 热备 |
Hot Standby |
从库在接收复制数据的同时允许只读查询 |