外观
PostgreSQL 逻辑复制监控
核心概念
逻辑复制监控的重要性
逻辑复制监控是确保PostgreSQL逻辑复制环境稳定运行的关键环节,通过监控可以:
- 及时发现复制延迟和故障
- 跟踪复制进度和性能
- 检测并处理复制冲突
- 确保数据一致性和完整性
- 优化复制性能
逻辑复制监控的主要内容
- 复制状态监控:监控发布者和订阅者的运行状态
- 性能监控:监控复制的延迟、吞吐量和资源消耗
- 冲突监控:监控和处理复制冲突
- 数据一致性监控:确保发布者和订阅者数据一致
- 错误监控:及时发现和处理复制错误
监控视图
发布者监控视图
pg_publication
查看所有发布的基本信息:
sql
SELECT * FROM pg_publication;pg_publication_tables
查看发布包含的表:
sql
SELECT * FROM pg_publication_tables;pg_replication_slots
查看复制槽状态,逻辑复制使用专用的复制槽:
sql
SELECT
slot_name,
plugin,
slot_type,
active,
restart_lsn,
confirmed_flush_lsn,
active_pid,
wal_status
FROM pg_replication_slots
WHERE slot_type = 'logical';订阅者监控视图
pg_subscription
查看所有订阅的配置信息:
sql
SELECT
subname,
subconninfo,
subpublications,
subenabled,
subslotname,
submissingpk,
subdisableonerror,
suborigin,
subrewrite
FROM pg_subscription;pg_stat_subscription
查看订阅的运行状态和性能指标:
sql
SELECT
subscription_name,
status,
received_lsn,
last_msg_receipt_time,
last_msg_send_time,
last_sync_time,
conflict_count,
replay_lsn,
replay_start_lsn,
replay_end_lsn,
last_replay_time
FROM pg_stat_subscription;pg_stat_subscription_tables
查看订阅中每个表的复制状态:
sql
SELECT
subscription_name,
relation_id,
relation_name,
last_replay_lsn,
last_replay_time
FROM pg_stat_subscription_tables;pg_replication_origin_status
查看复制原点状态,用于跟踪复制进度:
sql
SELECT
local_id,
external_id,
remote_lsn,
local_lsn
FROM pg_replication_origin_status;关键监控指标
1. 复制状态指标
| 指标名称 | 描述 | 监控视图 |
|---|---|---|
| status | 订阅状态(active/inactive) | pg_stat_subscription |
| subenabled | 订阅是否启用 | pg_subscription |
| active | 复制槽是否活跃 | pg_replication_slots |
2. 性能指标
| 指标名称 | 描述 | 监控视图 |
|---|---|---|
| received_lsn | 已接收的WAL位置 | pg_stat_subscription |
| replay_lsn | 已回放的WAL位置 | pg_stat_subscription |
| last_msg_receipt_time | 最后接收消息时间 | pg_stat_subscription |
| last_replay_time | 最后回放时间 | pg_stat_subscription |
| replication_delay | 复制延迟(计算得出) | - |
3. 冲突指标
| 指标名称 | 描述 | 监控视图 |
|---|---|---|
| conflict_count | 冲突计数 | pg_stat_subscription |
4. 数据一致性指标
| 指标名称 | 描述 | 监控方法 |
|---|---|---|
| 表行数差异 | 发布者和订阅者表行数差异 | 手动查询对比 |
| 数据校验和 | 数据完整性校验 | 使用pg_checksums或第三方工具 |
监控方法
1. SQL查询监控
监控复制状态
sql
-- 检查所有订阅状态
SELECT
subscription_name,
status,
CASE
WHEN status = 'active' THEN '正常'
ELSE '异常'
END AS status_desc,
last_msg_receipt_time,
last_replay_time
FROM pg_stat_subscription;监控复制延迟
sql
-- 计算复制延迟(秒)
SELECT
subscription_name,
status,
EXTRACT(EPOCH FROM (NOW() - last_msg_receipt_time)) AS receive_delay_seconds,
EXTRACT(EPOCH FROM (NOW() - last_replay_time)) AS replay_delay_seconds
FROM pg_stat_subscription;监控冲突情况
sql
-- 检查是否有冲突
SELECT
subscription_name,
conflict_count,
CASE
WHEN conflict_count > 0 THEN '存在冲突'
ELSE '无冲突'
END AS conflict_status
FROM pg_stat_subscription;监控复制槽状态
sql
-- 检查逻辑复制槽状态
SELECT
slot_name,
plugin,
slot_type,
active,
CASE
WHEN active THEN '活跃'
ELSE '非活跃'
END AS active_desc,
restart_lsn,
confirmed_flush_lsn,
wal_status
FROM pg_replication_slots
WHERE slot_type = 'logical';2. 日志分析
配置日志记录
确保PostgreSQL日志配置包含足够的复制信息:
sql
-- 修改日志配置
ALTER SYSTEM SET log_min_messages = 'warning';
ALTER SYSTEM SET log_min_error_statement = 'error';
ALTER SYSTEM SET log_replication_commands = on;
ALTER SYSTEM SET log_line_prefix = '%t [%p]: [%l-1] user=%u,db=%d,app=%a,client=%h ';
-- 应用配置
SELECT pg_reload_conf();分析日志
bash
# 查找逻辑复制相关日志
grep -i "subscription" /var/log/postgresql/postgresql-15-main.log
# 查找复制错误日志
grep -i "replication" /var/log/postgresql/postgresql-15-main.log | grep -i error
# 查找冲突日志
grep -i "conflict" /var/log/postgresql/postgresql-15-main.log3. 第三方监控工具
常用的PostgreSQL监控工具:
- Prometheus + Grafana:通过PostgreSQL exporter收集指标,使用Grafana可视化
- Zabbix:使用PostgreSQL模板监控复制状态
- pgAdmin:图形化界面监控复制状态
- Datadog:云原生监控平台,支持PostgreSQL复制监控
告警配置
1. 基于SQL的告警
监控复制状态告警
sql
-- 检查订阅是否活跃
SELECT
subscription_name
FROM pg_stat_subscription
WHERE status != 'active' OR last_msg_receipt_time < NOW() - INTERVAL '5 minutes';复制延迟告警
sql
-- 检查复制延迟是否超过阈值(例如30秒)
SELECT
subscription_name,
EXTRACT(EPOCH FROM (NOW() - last_replay_time)) AS replay_delay_seconds
FROM pg_stat_subscription
WHERE EXTRACT(EPOCH FROM (NOW() - last_replay_time)) > 30;冲突告警
sql
-- 检查是否有新的冲突
SELECT
subscription_name,
conflict_count
FROM pg_stat_subscription
WHERE conflict_count > 0;2. 基于日志的告警
使用日志监控工具(如ELK Stack、Graylog)设置日志告警规则,当出现以下关键字时触发告警:
- "ERROR: replication"
- "WARNING: subscription"
- "conflict detected"
- "could not apply logical replication change"
3. 第三方工具告警
使用Prometheus + Grafana设置告警规则:
yaml
# Prometheus告警规则示例
groups:
- name: postgresql-logical-replication
rules:
- alert: LogicalReplicationInactive
expr: postgresql_subscription_status != 1
for: 5m
labels:
severity: critical
annotations:
summary: "逻辑复制订阅 {{ $labels.subscription }} 处于非活跃状态"
description: "订阅 {{ $labels.subscription }} 已经5分钟处于非活跃状态"
- alert: LogicalReplicationDelay
expr: postgresql_subscription_replay_delay_seconds > 30
for: 5m
labels:
severity: warning
annotations:
summary: "逻辑复制延迟过高"
description: "订阅 {{ $labels.subscription }} 延迟已超过30秒"
- alert: LogicalReplicationConflicts
expr: postgresql_subscription_conflict_count > 0
for: 5m
labels:
severity: warning
annotations:
summary: "逻辑复制存在冲突"
description: "订阅 {{ $labels.subscription }} 存在 {{ $value }} 个冲突"最佳实践
1. 监控频率
- 关键指标:每1-5分钟监控一次
- 详细日志:每日分析一次,或出现告警时立即分析
- 全面检查:每周进行一次全面检查
2. 性能优化
- 定期清理复制槽:移除不再使用的复制槽,避免WAL堆积
- 优化复制槽参数:根据实际需求调整复制槽参数
- 合理设置冲突处理策略:根据业务需求选择合适的冲突处理策略
- 优化网络连接:确保发布者和订阅者之间的网络稳定
3. 数据一致性验证
- 定期验证数据一致性:使用pg_dump或第三方工具验证发布者和订阅者数据一致性
- 使用校验和:在创建表时启用数据校验和
- 定期进行全量同步:对于关键业务,定期进行全量同步
4. 故障处理
- 建立故障处理流程:明确复制故障的处理步骤和责任人
- 定期演练故障恢复:提高团队处理复制故障的能力
- 记录故障信息:详细记录故障的原因、处理方法和结果
常见问题(FAQ)
Q1:如何查看逻辑复制的具体进度?
A1:可以通过以下查询查看复制进度:
sql
SELECT
subscription_name,
received_lsn,
replay_lsn,
last_msg_receipt_time,
last_replay_time,
EXTRACT(EPOCH FROM (NOW() - last_replay_time)) AS replay_delay_seconds
FROM pg_stat_subscription;Q2:如何判断逻辑复制是否正常运行?
A2:可以从以下几个方面判断:
- 检查订阅状态:
SELECT status FROM pg_stat_subscription;应为active - 检查复制延迟:延迟不应持续增长
- 检查冲突计数:冲突计数不应持续增加
- 检查日志:没有复制相关的错误日志
Q3:如何处理逻辑复制延迟过高的问题?
A3:处理逻辑复制延迟过高的方法包括:
- 检查网络连接:确保发布者和订阅者之间的网络稳定
- 优化订阅者性能:检查订阅者的CPU、内存和磁盘使用情况
- 调整复制参数:例如增加
max_logical_replication_workers - 检查长事务:长事务会导致WAL堆积,影响复制速度
- 考虑使用多副本:对于高负载场景,考虑使用多个订阅者
Q4:如何监控逻辑复制的吞吐量?
A4:可以通过以下方法监控吞吐量:
sql
-- 计算每秒处理的WAL量(字节)
WITH previous AS (
SELECT
subscription_name,
replay_lsn,
last_replay_time
FROM pg_stat_subscription
), current AS (
SELECT
subscription_name,
replay_lsn,
last_replay_time
FROM pg_stat_subscription
) SELECT
p.subscription_name,
(pg_wal_lsn_diff(c.replay_lsn, p.replay_lsn) /
EXTRACT(EPOCH FROM (c.last_replay_time - p.last_replay_time))) AS wal_throughput_bytes_per_second
FROM previous p
JOIN current c ON p.subscription_name = c.subscription_name
WHERE c.last_replay_time > p.last_replay_time;Q5:如何防止复制槽堆积WAL?
A5:防止复制槽堆积WAL的方法包括:
- 定期监控复制槽状态:确保复制槽活跃
- 及时清理不再使用的复制槽:使用
SELECT pg_drop_replication_slot('slot_name'); - 设置合适的
max_slot_wal_keep_size:限制复制槽保留的WAL量 - 启用
hot_standby_feedback:防止主库过早回收WAL
Q6:如何验证发布者和订阅者的数据一致性?
A6:可以使用以下方法验证数据一致性:
- 使用pg_dump比较数据:分别从发布者和订阅者导出数据,然后比较
- 使用校验和工具:例如pg_checksums或第三方工具
- 使用逻辑复制验证工具:例如pg_verify_checksums
- 手动抽样检查:对关键表进行抽样检查
Q7:如何处理逻辑复制中的冲突?
A7:处理逻辑复制冲突的方法包括:
- 查看冲突信息:从日志中查看详细的冲突信息
- 分析冲突原因:确定冲突的类型和原因
- 手动解决冲突:根据冲突类型采取相应的解决方法
- 调整冲突处理策略:根据业务需求选择合适的冲突处理策略
- 优化数据模型:从根本上减少冲突的发生
Q8:如何监控多个订阅者的状态?
A8:可以使用以下查询监控多个订阅者的状态:
sql
SELECT
subscription_name,
status,
EXTRACT(EPOCH FROM (NOW() - last_msg_receipt_time)) AS receive_delay_seconds,
EXTRACT(EPOCH FROM (NOW() - last_replay_time)) AS replay_delay_seconds,
conflict_count
FROM pg_stat_subscription
ORDER BY subscription_name;对于跨多个服务器的订阅者,可以使用监控工具(如Prometheus + Grafana)进行集中监控。
