深入剖析 PostgreSQL 逻辑复制:pg_stat_replication 与 pg_stat_subscription 视图详解
PostgreSQL 的逻辑复制功能为数据库管理员 (DBA) 提供了灵活的数据同步解决方案。要有效地监控和排查逻辑复制问题,深入理解 pg_stat_replication 和 pg_stat_subscription 这两个系统视图至关重要。本文将详细解读这两个视图中各个字段的含义,并结合实际案例,阐述如何利用它们进行精细化的监控和故障排查。
逻辑复制基础回顾
在深入探讨这两个视图之前,咱们先简单回顾一下 PostgreSQL 逻辑复制的基本概念。逻辑复制基于发布者 (Publisher) 和订阅者 (Subscriber) 模型。发布者将数据变更(以 WAL 日志的形式)解码为逻辑变更流,订阅者接收并应用这些变更,从而实现数据的同步。这种方式允许用户选择性地复制表或数据库,提供了比物理复制更大的灵活性。
pg_stat_replication 视图详解
pg_stat_replication 视图提供了关于发布者端复制连接的详细信息。它主要关注的是从发布者到订阅者的连接状态和数据流。每个连接对应视图中的一行。
注意: 要查看此视图,你需要具有 pg_monitor 或超级用户权限。
下面是 pg_stat_replication 视图中各个字段的详细解释:
| 字段名 | 数据类型 | 描述 |
|---|---|---|
| pid | integer | 与此发布者关联的 walsender 进程的进程 ID。 |
| usesysid | oid | 连接到此 walsender 的用户的 OID。 |
| usename | name | 连接到此 walsender 的用户的名称。 |
| application_name | text | 连接到此 walsender 的应用程序的名称(通常是订阅者的名称)。 |
| client_addr | inet | 连接到此 walsender 的客户端的 IP 地址。如果此 walsender 是通过 Unix 域套接字连接的,则此列为空。 |
| client_hostname | text | 连接到此 walsender 的客户端的主机名(如果可用)。如果此 walsender 是通过 Unix 域套接字连接的,或者主机名查找被禁用,则此列为空。 |
| client_port | integer | 连接到此 walsender 的客户端的 TCP 端口号。如果此 walsender 是通过 Unix 域套接字连接的,则此列为 -1。 |
| backend_start | timestamp with time zone | 此 walsender 进程启动的时间。 |
| backend_xmin | xid | 此连接的 Horizon 之前的最早的事务 ID。这可以用来确定可以从发布服务器上安全删除的旧 WAL 日志的年龄。 |
| state | text | 此 walsender 进程的当前状态。可能的值为:startup、catchup、streaming、backup 和 stopping。 |
| sent_lsn | pg_lsn | 此 walsender 进程发送的最后一个 WAL 位置。 |
| write_lsn | pg_lsn | 此 walsender 进程写入磁盘的最后一个 WAL 位置。 |
| flush_lsn | pg_lsn | 此 walsender 进程刷新到磁盘的最后一个 WAL 位置。 |
| replay_lsn | pg_lsn | 此 walsender 进程报告给发布服务器的最后一个 WAL 位置(即订阅服务器已经接收、持久化并应用的)。 |
| write_lag | interval | 从将 WAL 写入本地磁盘到接收到此 walsender 进程的最新通知之间的时间。这可以用来衡量复制延迟,包括网络延迟和订阅服务器将 WAL 写入其本地磁盘的延迟。 |
| flush_lag | interval | 从将 WAL 刷新到本地磁盘到接收到此 walsender 进程的最新通知之间的时间。这可以用来衡量复制延迟,包括网络延迟和订阅服务器将 WAL 刷新到其本地磁盘的延迟。 |
| replay_lag | interval | 从将 WAL 应用到订阅服务器到接收到此 walsender 进程的最新通知之间的时间。这可以用来衡量复制延迟,包括网络延迟和订阅服务器应用 WAL 的延迟。 |
| sync_priority | integer | 此订阅的同步优先级。值越小,优先级越高。 |
| sync_state | text | 此订阅的同步状态。可能的值为:async、sync 和 quorum。 |
| reply_time | timestamp with time zone | 此 walsender 进程接收到来自订阅服务器的最新回复的时间。 |
重点字段解读与应用:
state字段: 反映了复制连接的当前状态。通常情况下,我们期望看到streaming状态,表示数据正在实时流式传输。如果状态为startup或catchup,则表明订阅者正在追赶发布者的进度。backup状态通常表示订阅者正在执行基础备份。stopping状态则表示连接正在关闭。sent_lsn、write_lsn、flush_lsn和replay_lsn: 这四个字段是监控复制延迟的关键。sent_lsn表示发布者已经发送的 WAL 位置,replay_lsn表示订阅者已经应用的 WAL 位置。它们之间的差距(replay_lag)反映了复制的总体延迟。write_lsn和flush_lsn则分别表示发布者将 WAL 写入和刷新到磁盘的位置,可以用来分析发布者端的性能瓶颈。*_lag字段:write_lag、flush_lag和replay_lag直接以时间间隔的形式展示了不同阶段的延迟,更直观地反映了复制的实时性。sync_priority和sync_state: 用于同步复制。当synchronous_commit设置为on、remote_apply、remote_write、local或off时,同步复制才起作用。sync_state显示了同步状态,sync_priority决定了同步订阅者的优先级。
示例场景:
假设你发现某个订阅者的 replay_lag 持续增长,而 write_lag 和 flush_lag 相对较小。这表明问题可能出在订阅者端,可能是订阅者服务器资源不足,或者应用 WAL 的速度跟不上接收速度。
pg_stat_subscription 视图详解
pg_stat_subscription 视图提供了关于订阅者端逻辑复制订阅的详细信息。每个订阅对应视图中的一行。与pg_stat_replication不同,pg_stat_subscription关注的是订阅者如何接收和应用来自发布者的数据。
注意: 要查看此视图,你需要具有 pg_monitor 或超级用户权限, 或者订阅的所有者。
下面是 pg_stat_subscription 视图中各个字段的详细解释:
| 字段名 | 数据类型 | 描述 |
|---|---|---|
| subid | oid | 订阅的 OID。 |
| subname | name | 订阅的名称。 |
| pid | integer | 订阅的 apply worker 进程的进程 ID。如果 worker 未运行,则此列为空。 |
| relid | oid | 如果此 worker 正在同步表,则为表的 OID;否则为空。 |
| received_lsn | pg_lsn | 从此发布者接收的最后一个 WAL 位置。 |
| last_msg_send_time | timestamp with time zone | 从此发布者接收到的最后一条消息的发送时间。 |
| last_msg_receipt_time | timestamp with time zone | 从此发布者接收到的最后一条消息的接收时间。 |
| latest_end_lsn | pg_lsn | 报告给发布服务器的最后一个 WAL 位置(即订阅服务器已经接收、持久化并应用的)。 |
| latest_end_time | timestamp with time zone | 报告给发布服务器的最后一个 WAL 位置的时间。 |
重点字段解读与应用:
pid和relid:pid字段显示了 apply worker 进程的 ID,可以用来监控 worker 进程的状态。如果pid为空,则表示 worker 进程未运行,可能是订阅被禁用或者出现了错误。relid字段显示了当前正在同步的表的 OID,有助于了解同步的进度。received_lsn和latest_end_lsn:received_lsn表示订阅者已经从发布者接收到的 WAL 位置,latest_end_lsn表示订阅者已经应用的 WAL 位置。它们之间的差距可以反映订阅者端的应用延迟。last_msg_send_time和last_msg_receipt_time: 这两个字段可以用来计算网络延迟。last_msg_receipt_time-last_msg_send_time的结果就是网络传输消息所需的时间。
示例场景:
如果你发现某个订阅的 received_lsn 和 latest_end_lsn 之间的差距持续扩大,而 last_msg_send_time 和 last_msg_receipt_time 之间的差距相对稳定。这表明网络传输正常,问题可能出在订阅者应用 WAL 的速度上。你需要检查订阅者服务器的资源使用情况,或者查看是否有长时间运行的事务阻塞了 WAL 的应用。
结合使用两个视图进行全面监控
pg_stat_replication 和 pg_stat_subscription 视图提供了互补的信息。pg_stat_replication 关注发布者端的连接和发送状态,而 pg_stat_subscription 关注订阅者端的接收和应用状态。将这两个视图结合起来,可以更全面地了解逻辑复制的整体情况,更准确地定位问题。
以下是一些建议的监控策略:
- 监控复制延迟: 定期检查
pg_stat_replication中的replay_lag和pg_stat_subscription中received_lsn与latest_end_lsn的差距。设置合理的阈值,并在延迟超过阈值时发出警报。 - 监控连接状态: 检查
pg_stat_replication中的state字段,确保复制连接处于streaming状态。如果出现其他状态,需要及时调查原因。 - 监控 worker 进程: 检查
pg_stat_subscription中的pid字段,确保 apply worker 进程正在运行。如果pid为空,需要检查订阅的状态和错误日志。 - 监控网络延迟: 计算
pg_stat_subscription中last_msg_receipt_time和last_msg_send_time的差值,监控网络传输的延迟。 - 分析性能瓶颈: 结合
pg_stat_replication中的sent_lsn、write_lsn、flush_lsn和replay_lsn,以及pg_stat_subscription中的received_lsn和latest_end_lsn,分析复制过程中的性能瓶颈是出现在发布者端、网络传输还是订阅者端。 - 同步复制监控: 结合
pg_stat_replication中sync_state和sync_priority,来确定同步复制是否按预期工作。当sync_state不是sync或quorum时,表示同步复制可能存在问题。
总结
pg_stat_replication 和 pg_stat_subscription 是 PostgreSQL 逻辑复制监控和故障排查的重要工具。通过深入理解这两个视图中各个字段的含义,并结合实际场景进行分析,DBA 可以更有效地管理逻辑复制,确保数据的及时同步和系统的稳定运行。希望本文能帮助你更好地掌握 PostgreSQL 逻辑复制的监控和调优。记住,实践出真知,多动手操作,多观察,你就能成为 PostgreSQL 逻辑复制的专家!
补充说明:
除了这两个视图,PostgreSQL 还提供了一些其他的工具和函数,可以用来监控和管理逻辑复制,例如:
pg_replication_slots视图: 显示复制槽的信息,复制槽用于确保发布者不会删除订阅者仍然需要的 WAL 日志。pg_logical_slot_get_changes()函数: 可以用来手动读取逻辑复制槽中的变更。pg_create_logical_replication_slot()函数: 用于创建逻辑复制槽。pg_drop_replication_slot()函数: 用于删除逻辑复制槽。
掌握这些工具和函数,可以进一步提升你对 PostgreSQL 逻辑复制的掌控能力。