PostgreSQL 复制(同步和异步复制)是数据库社区中最广泛使用的功能之一。如今,人们正在构建高可用性集群或使用复制来创建只读
副本来分散工作负载。这里需要注意的是,如果您使用复制,则必须确保您的集群受到正确监控。
这篇文章的目的是解释一些基础知识,以确保您的 PostgreSQL 集群保持健康。
pg_stat_replication:检查当前状态
监控复制的最佳方法是使用 pg_stat_replication
,它包含很多重要信息。视图如下所示:
test=# \d pg_stat_replication
View "pg_catalog.pg_stat_replication"
Column | Type | Collation | Nullable | Default
-----------------+-------------------------+-----------+----------+---------
pid | integer | | |
usesysid | oid | | |
usename | name | | |
application_name | text | | |
client_addr | inet | | |
client_hostname | text | | |
client_port | integer | | |
backend_start | timestamp with time zone| | |
backend_xmin | xid | | |
state | text | | |
sent_lsn | pg_lsn | | |
write_lsn | pg_lsn | | |
flush_lsn | pg_lsn | | |
replay_lsn | pg_lsn | | |
write_lag | interval | | |
flush_lag | interval | | |
replay_lag | interval | | |
sync_priority | integer | | |
sync_state | text | | |
reply_time | timestamp with time zone| | |
多年来,此视图中的列数大幅增加。不过,我们首先讨论一些基本原理。
pg_stat_replication:WAL sender信息
人们常说 pg_stat_replication
位于“primary”上。这不完全正确。该视图的作用是公开有关 wal_sender 进程的信息。换句话说:如
果你正在运行级联复制,这意味着当一个从服务器复制到其他从服务器时,它可能也会显示条目。这是一张说明情况的图片:
对于每个 WAL sender进程,您将得到一个条目。重要的是,每个服务器只能看到链中的下一个服务器——发送服务器永远不会“看穿”从服务器。换句话说:在级联复制的情况下,您必须要求每个发送服务器获取概览。
还有更多:人们通常必须确定备库是否是最新的。这里有很多相关的事情:
- sent_lsn:已经通过网络发送了多少 WAL?
- write_lsn:已向操作系统发送了多少 WAL?(未刷盘)
- lush_lsn:有多少 WAL 已刷新到磁盘?
- replay_lsn:已经重播了多少 WAL,因此对查询可见?
下图说明了这些字段:
这里需要注意的是,PostgreSQL 提供了一种特殊的数据类型来表示这些数据:pg_lsn
可以轻松地找出当前的 WAL 位置。下面是它的工作原理:
test=# SELECT pg_current_wal_lsn();
pg_current_wal_lsn
--------------------
3/DA06D240
(1 row)
这里值得注意的是可以进行计算:
test=# SELECT pg_current_wal_lsn() - '3/B549A845'::pg_lsn;
?column?
-----------
616376827
(1 row)
PostgreSQL 提供了各种运算符来执行此类计算。换句话说:很容易找出备库落后了多远。
flush_lsn 与 replay_lsn
人们一直在问我们flush_lsn
和 replay_lsn
之间有什么区别。好吧,让我们深入研究一下:当WAL从主节点流向从节点时,它首先通过
网络发送,然后发送到操作系统,最后将事务刷新到磁盘,以确保持久性(=崩溃安全)。flush_lsn
显然表示最后一次刷写到磁盘的WAL
位置。现在的问题是:数据刷新后是否可见?答案是不,可能会有复制冲突。在发生复制冲突的情况下,WAL会持久化在备库上,只有
在冲突解决后才会重放。换句话说,可能发生的情况是,数据存储在从服务器上,但尚未重放使得用户最终可以访问。
注意这一点很重要,因为复制冲突发生的频率可能比您想象的要高。如果您看到如下消息,则说明您遇到了复制冲突:
ERROR: canceling statement due to conflict with recovery
DETAIL: User query might have needed to see row versions that must be removed.
复制滞后
有时需要确定复制延迟量(以秒为单位)。到目前为止,我们已经看到了两个服务器之间的距离(以字节为单位)。如果您想测量滞后,
可以查看 _lag
列。这些列的数据类型是“间隔”,因此您可以看到延迟是多少秒甚至几分钟。如果复制工作正常,延迟通常非常非常小
(毫秒)。但是,您可能想要监视它。
需要注意的是:如果您正在运行大规模导入,例如 VACUUM 或其他一些昂贵的操作,很容易发生磁盘吞吐量高于网络带宽的情况。在这
种情况下,备库很有可能落后。您必须容忍这种情况,并确保警报不会过早启动。
pgwatch2:现成的工具
要监视复制,您可以依赖我刚才展示的手动魔术。然而,也有很多现成的工具来促进这项任务。我们可以推荐pgwatch2,它可以作为一
个容器免费下载。