外观
PostgreSQL 经典故障经验教训
监控告警篇
1. 磁盘空间监控不可忽视
经验教训:WAL日志目录磁盘空间耗尽导致数据库挂起的故障,暴露了监控配置的不足。
最佳实践:
- 配置全面的磁盘空间监控,包括数据目录、WAL日志目录、归档目录和临时目录
- 设置合理的告警阈值,建议磁盘使用率超过80%时触发告警
- 配置多级告警机制,包括邮件、短信和电话告警
- 定期检查监控规则的有效性
实施建议:
bash
# 使用Prometheus + Grafana监控磁盘空间
# Prometheus配置示例
- job_name: 'node'
static_configs:
- targets: ['node-exporter:9100']
# Grafana告警规则示例
ALERT DiskSpaceWarning
IF (node_filesystem_size_bytes - node_filesystem_free_bytes) / node_filesystem_size_bytes * 100 > 80
FOR 5m
LABELS { severity = "warning" }
ANNOTATIONS {
summary = "磁盘空间警告",
description = "{{ $labels.instance }} 的 {{ $labels.mountpoint }} 分区使用率超过80%"
}2. 监控指标需覆盖关键组件
经验教训:主从复制延迟问题未及时发现,导致从库数据严重过期。
最佳实践:
- 监控复制延迟、WAL发送和接收状态
- 监控数据库连接数、慢查询数和锁等待
- 监控PostgreSQL后台进程状态
- 监控系统资源使用情况(CPU、内存、I/O、网络)
实施建议:
sql
-- 使用pg_stat_statements监控慢查询
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
-- 使用pg_stat_replication监控复制状态
SELECT client_addr, state, sent_lsn, write_lsn, flush_lsn, replay_lsn,
now() - pg_last_xact_replay_timestamp() AS replication_delay
FROM pg_stat_replication;备份恢复篇
1. 备份策略需完善
经验教训:WAL日志归档失败导致WAL日志无法清理,最终引发磁盘空间问题。
最佳实践:
- 实施3-2-1备份策略:3份备份,2种不同介质,1份异地存储
- 定期测试备份的可恢复性
- 配置备份监控和告警
- 区分全量备份和增量备份
实施建议:
bash
# 使用pg_probackup配置自动备份
pg_probackup stanza-create -B /path/to/backup --stanza postgres
pg_probackup backup -B /path/to/backup --stanza postgres -b full
pg_probackup backup -B /path/to/backup --stanza postgres -b incr
# 定期测试恢复
pg_probackup restore -B /path/to/backup --stanza postgres --recovery-target-time '2026-01-01 12:00:00'2. WAL日志管理需谨慎
经验教训:WAL日志保留策略不当导致磁盘空间耗尽。
最佳实践:
- 根据备份策略设置合理的WAL日志保留时间
- 配置自动清理机制
- 监控WAL日志生成速率
- 考虑使用WAL压缩
实施建议:
sql
-- 配置WAL日志保留
ALTER SYSTEM SET wal_keep_size = '2GB';
-- 配置归档命令
ALTER SYSTEM SET archive_command = 'rsync -a %p /path/to/archive/%f';
-- 配置WAL压缩
ALTER SYSTEM SET wal_compression = 'on';
-- 重新加载配置
SELECT pg_reload_conf();配置管理篇
1. 参数配置需验证
经验教训:配置参数未验证导致性能问题。
最佳实践:
- 配置变更前在测试环境验证
- 使用配置管理工具管理数据库配置
- 记录所有配置变更
- 定期审查配置合理性
实施建议:
bash
# 使用Ansible管理PostgreSQL配置
# Ansible playbook示例
- name: Configure PostgreSQL parameters
hosts: postgres_servers
become: yes
tasks:
- name: Update postgresql.conf
lineinfile:
path: /var/lib/pgsql/15/data/postgresql.conf
regexp: '^shared_buffers'
line: 'shared_buffers = 2GB'
notify: restart postgresql
handlers:
- name: restart postgresql
systemd:
name: postgresql-15
state: restarted2. 自动维护需重视
经验教训:自动统计信息收集配置不当导致索引失效。
最佳实践:
- 启用自动清理和分析
- 为大表配置专门的自动维护参数
- 监控自动维护任务的执行情况
- 定期手动执行VACUUM和ANALYZE
实施建议:
sql
-- 配置自动维护
ALTER SYSTEM SET autovacuum = on;
ALTER SYSTEM SET autovacuum_max_workers = 3;
ALTER SYSTEM SET autovacuum_naptime = '1min';
ALTER SYSTEM SET autovacuum_analyze_scale_factor = 0.05;
-- 为大表配置专门参数
ALTER TABLE large_table SET (
autovacuum_analyze_scale_factor = 0.02,
autovacuum_vacuum_scale_factor = 0.05
);权限管理篇
1. 最小权限原则必须遵循
经验教训:权限配置错误导致数据泄露风险。
最佳实践:
- 遵循最小权限原则
- 使用角色管理权限
- 定期审查用户权限
- 配置详细的权限审计
实施建议:
sql
-- 创建角色而非直接授予用户权限
CREATE ROLE readonly WITH NOSUPERUSER NOCREATEDB NOCREATEROLE LOGIN;
GRANT CONNECT ON DATABASE mydb TO readonly;
GRANT USAGE ON SCHEMA public TO readonly;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly;
ALTER DEFAULT PRIVILEGES GRANT SELECT ON TABLES IN SCHEMA public TO readonly;
-- 定期审查权限
SELECT grantee, privilege_type, table_name
FROM information_schema.role_table_grants
WHERE grantee NOT IN ('postgres', 'public');2. 安全审计不可缺少
经验教训:权限变更未审计导致安全事件追查困难。
最佳实践:
- 启用详细的安全审计日志
- 监控异常访问行为
- 定期分析审计日志
- 配置审计日志的保留策略
实施建议:
sql
-- 启用审计日志
ALTER SYSTEM SET log_statement = 'all';
ALTER SYSTEM SET log_connections = on;
ALTER SYSTEM SET log_disconnections = on;
ALTER SYSTEM SET log_line_prefix = '%t [%p]: [%l-1] user=%u,db=%d,app=%a,client=%h ';
ALTER SYSTEM SET log_duration = on;
-- 重新加载配置
SELECT pg_reload_conf();性能优化篇
1. 索引设计需合理
经验教训:索引设计不当导致查询性能急剧下降。
最佳实践:
- 根据查询模式设计索引
- 避免过多冗余索引
- 定期分析索引使用情况
- 考虑使用部分索引和表达式索引
实施建议:
sql
-- 分析索引使用情况
SELECT relname, indexrelname, idx_scan, idx_tup_read, idx_tup_fetch
FROM pg_stat_user_indexes
ORDER BY idx_scan ASC;
-- 创建合适的索引
CREATE INDEX CONCURRENTLY idx_users_email ON users(email);
-- 使用部分索引
CREATE INDEX idx_orders_status ON orders(status) WHERE status = 'active';
-- 使用表达式索引
CREATE INDEX idx_users_lower_email ON users(lower(email));2. 事务管理需优化
经验教训:长事务导致锁竞争和性能问题。
最佳实践:
- 尽量缩短事务长度
- 避免在事务中执行耗时操作
- 配置合理的事务超时
- 监控长时间运行的事务
实施建议:
sql
-- 配置事务超时
ALTER SYSTEM SET statement_timeout = '60s';
ALTER SYSTEM SET idle_in_transaction_session_timeout = '300s';
-- 监控长时间运行的事务
SELECT pid, usename, datname, query_start, now() - query_start AS duration, query
FROM pg_stat_activity
WHERE state <> 'idle'
AND now() - query_start > interval '5 minutes'
ORDER BY duration DESC;高可用篇
1. 复制配置需完善
经验教训:主从复制配置不当导致复制延迟。
最佳实践:
- 配置合适的复制参数
- 监控复制状态
- 测试故障转移流程
- 考虑使用多副本架构
实施建议:
sql
-- 主库配置
ALTER SYSTEM SET max_wal_senders = 10;
ALTER SYSTEM SET wal_level = 'replica';
ALTER SYSTEM SET synchronous_commit = 'remote_write';
-- 从库配置
ALTER SYSTEM SET hot_standby = on;
ALTER SYSTEM SET hot_standby_feedback = on;
ALTER SYSTEM SET max_worker_processes = 8;
ALTER SYSTEM SET max_parallel_workers = 8;
-- 重新加载配置
SELECT pg_reload_conf();2. 故障转移需测试
经验教训:故障转移流程未测试导致故障恢复时间延长。
最佳实践:
- 定期测试故障转移流程
- 确保故障转移自动化
- 测试数据一致性
- 验证应用程序切换逻辑
实施建议:
bash
# 使用Patroni进行自动故障转移
# Patroni配置示例
scope: postgres-cluster
namespace: /db/
name: postgres-1
restapi:
listen: 0.0.0.0:8008
connect_address: 192.168.1.101:8008
etcd:
host: 192.168.1.100:2379
bootstrap:
dcs:
ttl: 30
loop_wait: 10
retry_timeout: 10
maximum_lag_on_failover: 1048576
postgresql:
use_pg_rewind: true
use_slots: true
parameters:
wal_level: replica
hot_standby: "on"
wal_keep_size: 2GB常见问题(FAQ)
Q1:如何建立有效的监控体系?
A1:可以采取以下步骤:
- 识别关键监控指标
- 选择合适的监控工具(如Prometheus + Grafana)
- 配置合理的告警阈值
- 建立多级告警机制
- 定期审查监控规则
Q2:如何优化PostgreSQL性能?
A2:可以从以下几个方面入手:
- 优化配置参数
- 合理设计索引
- 优化查询语句
- 管理长事务
- 配置合理的自动维护
Q3:如何确保数据库安全性?
A3:可以采取以下措施:
- 遵循最小权限原则
- 启用安全审计
- 定期更新和补丁
- 配置网络访问控制
- 使用加密连接
Q4:如何设计可靠的备份策略?
A4:可以遵循以下原则:
- 实施3-2-1备份策略
- 结合全量备份和增量备份
- 定期测试备份恢复
- 配置备份监控和告警
- 考虑异地备份
Q5:如何管理WAL日志?
A5:可以采取以下措施:
- 根据备份策略设置合理的保留时间
- 配置自动清理机制
- 监控WAL日志生成速率
- 考虑使用WAL压缩
- 确保归档命令可靠
Q6:如何优化索引设计?
A6:可以采取以下步骤:
- 分析查询模式
- 避免过多冗余索引
- 定期分析索引使用情况
- 考虑使用部分索引和表达式索引
- 使用CONCURRENTLY创建和重建索引
Q7:如何处理长事务?
A7:可以采取以下措施:
- 尽量缩短事务长度
- 配置合理的事务超时
- 监控长时间运行的事务
- 避免在事务中执行耗时操作
- 使用合适的事务隔离级别
Q8:如何测试故障转移?
A8:可以采取以下步骤:
- 制定详细的故障转移测试计划
- 在测试环境定期演练
- 测试数据一致性
- 验证应用程序切换逻辑
- 记录测试结果并优化流程
