使用Postgresql逻辑复制,怎么知道订阅者被追上了?

mli*_*ner 7 postgresql replication

Postgresql 有一些有趣的监控工具,用于监控新的逻辑复制系统的进度,但我不是很了解它们。我知道的两个工具是:

pg_stat_replication
Run Code Online (Sandbox Code Playgroud)

它是兄弟姐妹:

pg_stat_subscription
Run Code Online (Sandbox Code Playgroud)

我已经阅读了这些文档,但他们没有说明如何知道副本是否实际同步,并且解释这些表对我来说似乎并不明显。有人可以解释一下吗?

小智 7

去年我在 Postgres 10 上使用了复制,我在理解如何监控过程时遇到了同样的问题,因为文档不够清楚。不管怎样,我会试着给你一个例子来检查监控是否正在进行。

发布者方面,您可以检查以下几点:

  • pg_catalog.pg_publication;
  • pg_catalog.pg_publication_tables;
  • pg_current_wal_lsn();

我将创建一个包含两个表的发布“test_publication”:t_1t_2. 我不会介绍先决条件(用户、角色等)。

test_logical_replication=# create publication test_publication for table t_1, t_2;  
CREATE PUBLICATION  
test_logical_replication=# select * from pg_catalog.pg_publication;  
pubname      | pubowner | puballtables | pubinsert | pubupdate | pubdelete  
-----------------+----------+--------------+-----------+-----------+-----------  
test_publication |       10 | f            | t         | t         | t  
(1 row) 

test_logical_replication=# select * from pg_publication_tables;    
    pubname      | schemaname | tablename  
    ------------------+------------+-----------  
     test_publication | public     | t_1  
     test_publication | public     | t_2  
    (2 rows)  
Run Code Online (Sandbox Code Playgroud)

订阅者方面:

test_logical_replication_subscriber=# create subscription test_subscription CONNECTION 'dbname=test_logical_replication host=XXX user=repuser' PUBLICATION test_publication;  
NOTICE:  created replication slot "test_subscription" on publisher   
CREATE SUBSCRIPTION 
Run Code Online (Sandbox Code Playgroud)

有趣的信息在表中pg_catalog.pg_stat_subscription
这里的重要列是:

  • received_lsn:收到的最后一个预写日志位置。
  • last_msg_send_time:从发布者收到的最后一条消息的发送时间。
  • last_msg_receipt_time:从发布者收到的最后一条消息的接收时间。
  • latest_end_lsn:报告给发布者的最后一个预写日志位置。
  • latest_end_time:上次向发布者报告的预写日志位置的时间。

您必须检查这些列以了解正在发生的事情。
首先检查两个数据库是否同步;

出版商方面

test_logical_replication=> select pg_current_wal_lsn();  
 pg_current_wal_lsn  
--------------------  
 0/8EB83768     
Run Code Online (Sandbox Code Playgroud)

在开始新的插入之前,这显示了我们现在所在的 WAL 文件中的位置。

我们可以检查订阅者此时两个数据库是否同步,因为pg_current_wal_lsn()发布者返回 的值与列中received_lsnlatest_end_lsn订阅者上的值匹配:

test_logical_replication_subscriber=# select received_lsn, latest_end_lsn from pg_catalog.pg_stat_subscription;  

received_lsn    | latest_end_lsn  
----------------+------------------     
 0/8EB83768     | 0/8EB83768        
Run Code Online (Sandbox Code Playgroud)

我将向 table 添加 4000 行t_1,看看发布者会发生什么:

test_logical_replication=> insert into t_1 select id+1, txt||'--BB' from t_1;  
INSERT 0 4000  


test_logical_replication=> select pg_current_wal_lsn();  
 pg_current_wal_lsn
--------------------
 0/8EC4B9D0             <<< this value in increasing
(1 row)

test_logical_replication=> select pg_current_wal_lsn();
 pg_current_wal_lsn
--------------------
 0/8EC4DE78             <<< this value in increasing
(1 row)

test_logical_replication=> select pg_current_wal_lsn();
 pg_current_wal_lsn
--------------------
 0/8EC4DEB0             <<< this value in increasing
(1 row) 

test_logical_replication=> select pg_current_wal_lsn();
 pg_current_wal_lsn
--------------------
 0/8EC4DEB0            <<< same value, WAL sending has finished
(1 row)  
Run Code Online (Sandbox Code Playgroud)

让我们看看pg_catalog.pg_stat_subscription订阅者复制过程中值是如何变化的:

test_logical_replication_subscriber=# select received_lsn,last_msg_send_time,last_msg_receipt_time,latest_end_lsn,latest_end_time from pg_catalog.pg_stat_subscription;
 received_lsn |      last_msg_send_time       |    last_msg_receipt_time     | latest_end_lsn |        latest_end_time  
--------------+-------------------------------+------------------------------+----------------+-------------------------------
 0/8EC4B9D0   | 2018-12-17 11:39:56.014564+01 | 2018-12-17 11:39:56.07322+01 | 0/8EC4B9D0     | 2018-12-17 11:39:56.014564+01
(1 row)  

test_logical_replication_subscriber=# select received_lsn,last_msg_send_time,last_msg_receipt_time,latest_end_lsn,latest_end_time from pg_catalog.pg_stat_subscription;
 received_lsn |      last_msg_send_time       |     last_msg_receipt_time     | latest_end_lsn |        latest_end_time
--------------+-------------------------------+-------------------------------+----------------+-------------------------------
 0/8EC4BA08   | 2018-12-17 11:39:56.737101+01 | 2018-12-17 11:39:56.736303+01 | 0/8EC4BA08     | 2018-12-17 11:39:56.737101+01  
(1 row)  

test_logical_replication_subscriber=# select received_lsn,last_msg_send_time,last_msg_receipt_time,latest_end_lsn,latest_end_time from pg_catalog.pg_stat_subscription;
 received_lsn |      last_msg_send_time       |     last_msg_receipt_time     | latest_end_lsn |        latest_end_time
--------------+-------------------------------+-------------------------------+----------------+-------------------------------
 0/8EC4DE78   | 2018-12-17 11:40:04.184765+01 | 2018-12-17 11:40:04.183937+01 | 0/8EC4DE78     | 2018-12-17 11:40:04.184765+01
(1 row)  

 test_logical_replication_subscriber=# select received_lsn,last_msg_send_time,last_msg_receipt_time,latest_end_lsn,latest_end_time from pg_catalog.pg_stat_subscription;
 received_lsn |      last_msg_send_time       |   last_msg_receipt_time    | latest_end_lsn |        latest_end_time
--------------+-------------------------------+----------------------------+----------------+-------------------------------
 0/8EC4DEB0   | 2018-12-17 11:40:17.153797+01 | 2018-12-17 11:40:17.153+01 | 0/8EC4DEB0     | 2018-12-17 11:40:17.153797+01
(1 row)   
Run Code Online (Sandbox Code Playgroud)

如您所见,在订阅者上,四列显示了 WAL 如何从发布者到达以及它是如何应用的。在列的时间差last_msg_send_time,并last_msg_receipt_time能提供关于发布者和用户之间的滞后信息。
在这种情况下,两台服务器位于同一数据中心的不同子网上。

考虑到我使用的两台服务器是测试服务器,它们之间的同步并不完美。(订阅服务器根本没有配置 NTP 服务器)。


小智 5

在发布者(提供者)端检查此 SQL 的输出(对于版本> = PG10)以获得滞后:

select   pid, client_addr, state, sync_state,  
         pg_wal_lsn_diff(sent_lsn, write_lsn) as write_lag,  
         pg_wal_lsn_diff(sent_lsn, flush_lsn) as flush_lag,  
         pg_wal_lsn_diff(sent_lsn, replay_lsn) as replay_lag
from pg_stat_replication;
Run Code Online (Sandbox Code Playgroud)

如果您使用pglogical扩展,您可以检查表的复制状态。如果以下查询返回订阅者端有问题的表(例如一致性问题):

SELECT sub.sub_name, sync_kind, sync_relname, sync_status 
  FROM pglogical.local_sync_status stat 
  JOIN pglogical.subscription sub ON sub.sub_id = stat.sync_subid 
 WHERE sync_status!='r'
Run Code Online (Sandbox Code Playgroud)