Skip to content

PostgreSQL 逻辑复制监控

核心概念

逻辑复制监控的重要性

逻辑复制监控是确保PostgreSQL逻辑复制环境稳定运行的关键环节,通过监控可以:

  • 及时发现复制延迟和故障
  • 跟踪复制进度和性能
  • 检测并处理复制冲突
  • 确保数据一致性和完整性
  • 优化复制性能

逻辑复制监控的主要内容

  1. 复制状态监控:监控发布者和订阅者的运行状态
  2. 性能监控:监控复制的延迟、吞吐量和资源消耗
  3. 冲突监控:监控和处理复制冲突
  4. 数据一致性监控:确保发布者和订阅者数据一致
  5. 错误监控:及时发现和处理复制错误

监控视图

发布者监控视图

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.log

3. 第三方监控工具

常用的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:可以从以下几个方面判断:

  1. 检查订阅状态:SELECT status FROM pg_stat_subscription; 应为active
  2. 检查复制延迟:延迟不应持续增长
  3. 检查冲突计数:冲突计数不应持续增加
  4. 检查日志:没有复制相关的错误日志

Q3:如何处理逻辑复制延迟过高的问题?

A3:处理逻辑复制延迟过高的方法包括:

  1. 检查网络连接:确保发布者和订阅者之间的网络稳定
  2. 优化订阅者性能:检查订阅者的CPU、内存和磁盘使用情况
  3. 调整复制参数:例如增加max_logical_replication_workers
  4. 检查长事务:长事务会导致WAL堆积,影响复制速度
  5. 考虑使用多副本:对于高负载场景,考虑使用多个订阅者

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的方法包括:

  1. 定期监控复制槽状态:确保复制槽活跃
  2. 及时清理不再使用的复制槽:使用SELECT pg_drop_replication_slot('slot_name');
  3. 设置合适的max_slot_wal_keep_size:限制复制槽保留的WAL量
  4. 启用hot_standby_feedback:防止主库过早回收WAL

Q6:如何验证发布者和订阅者的数据一致性?

A6:可以使用以下方法验证数据一致性:

  1. 使用pg_dump比较数据:分别从发布者和订阅者导出数据,然后比较
  2. 使用校验和工具:例如pg_checksums或第三方工具
  3. 使用逻辑复制验证工具:例如pg_verify_checksums
  4. 手动抽样检查:对关键表进行抽样检查

Q7:如何处理逻辑复制中的冲突?

A7:处理逻辑复制冲突的方法包括:

  1. 查看冲突信息:从日志中查看详细的冲突信息
  2. 分析冲突原因:确定冲突的类型和原因
  3. 手动解决冲突:根据冲突类型采取相应的解决方法
  4. 调整冲突处理策略:根据业务需求选择合适的冲突处理策略
  5. 优化数据模型:从根本上减少冲突的发生

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)进行集中监控。