经典问题
PostgreSQL 的问题更多集中在:数据一致性、性能、并发、运维与可用性。
表现
- 查询偶发或持续变慢
- EXPLAIN 显示 Seq Scan
- 同样 SQL 在不同时间性能差异大
根因
- 缺索引 / 索引设计不合理
- 统计信息不准(未 ANALYZE)
- 错误的数据类型(char / varchar / timestamptz)
- LIKE %xxx% 无法使用 B-Tree
- JOIN 顺序错误
- 返回列过多(SELECT *)
对策
- EXPLAIN (ANALYZE, BUFFERS)
- 合理使用:
- B-Tree / GIN / BRIN
- pg_trgm
- 定期 ANALYZE
- 明确字段类型(时间用 TIMESTAMPTZ)
- 拆 SQL,而不是堆 SQL
表现
- UPDATE / DELETE 卡住
- 出现 deadlock detected
- 高并发写入性能急剧下降
根因
- 长事务
- 不合理的 UPDATE 顺序
- SELECT FOR UPDATE 滥用
- 外键级联导致隐式锁
对策
- 控制事务粒度(短事务)
- 固定访问顺序
- 避免长时间 HOLD 事务
- 使用:
SELECT * FROM pg_locks;
表现
- 表越来越大
- 查询越来越慢
- VACUUM 跑不动
根因
- UPDATE / DELETE 多
- autovacuum 参数不合理
- 长事务阻止 vacuum
对策
- 调整 autovacuum
- 定期:
VACUUM (ANALYZE);
VACUUM FULL; -- 仅低峰
- 监控:
n_dead_tup
表现
- 读到“旧数据”
- 幻读 / 不可重复读理解错误
根因
- 不理解 PostgreSQL 的隔离级别
- 误用 READ COMMITTED
对策
- 理解隔离级别:
- READ COMMITTED
- REPEATABLE READ
- SERIALIZABLE
- 金融 / 结算使用更高隔离
表现
- 不同时区数据混乱
- 日志时间不一致
根因
- 使用 TIMESTAMP 而不是 TIMESTAMPTZ
对策
- 日志 / 事件 / 审计:必须 TIMESTAMPTZ
- 统一 UTC 存储
常见误区
- COUNT(*) 很快(错)
- 索引越多越好(错)
- CHAR 比 VARCHAR 快(错)
- 自动 VACUUM = 万能(错)
表现
- 查询慢但 CPU 空闲
- iowait 高
根因
- 随机 IO
- WAL 写入压力
- 索引过多
对策
- SSD / NVMe
- 调整:
shared_buffers
effective_cache_size
wal_buffers
- WAL 独立磁盘
表现
- 数据库停止服务
- WAL 目录暴涨
根因
- 没有备库
- 复制槽未释放
- 备份失败
对策
- 监控:
pg_replication_slots;
- 定期清理失效 slot
- pgBackRest / WAL 归档
表现
- 恢复失败
- backup.info 丢失
根因
- 只做逻辑备份
- 未验证恢复
- WAL 不完整
对策
- 物理备份 + WAL
- 定期演练恢复
- 使用 pgBackRest
表现
- 读从库数据旧
- 应用异常
根因
- 同步复制配置错误
- 网络延迟
- 大事务
对策
- 区分:
- 同步复制
- 异步复制
- 监控 replication lag
表现
- 数据库被 OOM Killer 杀掉
根因
- work_mem 设置过大
- 高并发 JOIN / SORT
对策
- work_mem × 并发数 ≠ 总内存
- 使用 LIMIT
- 优化 SQL
表现
- COUNT 很慢
- 行数显示不准
根因
- PostgreSQL 不维护精确行数
对策
- 使用:
pg_stat_all_tables.n_live_tup
表现
- 升级后扩展不可用
- TimescaleDB / pg_trgm 报错
根因
- 主版本升级
- 扩展未匹配
对策
- 升级前验证:
- 扩展支持版本
- 使用 pg_upgrade
| 系统 | 核心问题 |
|---|---|
| Redis | 穿透 / 击穿 / 雪崩 |
| PostgreSQL | 慢 SQL / 锁 / 膨胀 / WAL / 备份 / 时间 / 内存 |
PostgreSQL 的“七宗罪”👇
SQL 慢、锁乱、表膨胀、WAL 爆、备份假、时间错、内存炸