如何检查PostgreSQL中的复制延迟?

Alf*_*62 22 postgresql replication

我想在PostgreSQL 9.3中使用流复制来测量插入数据到master-table和slave-table之间的时间.为此,我创建了表test_time,其中包含2个字段id(serial),t(text).之后添加了一个触发器:

cur_time:=to_char(current_timestamp, 'HH12:MI:SS:MS:US'); update test_time set t=cur_time where id=new.id;

但两张桌子的时间都是一样的.我该如何测量延迟时间

dbe*_*hur 20

Alf162在对Craig Ringer的回答的评论中提到了一个很好的解决方案; 所以我加上这个来澄清.

PostgreSQL有一个管理函数pg_last_xact_replay_timestamp(),它返回恢复期间重放的最后一个事务的时间戳.这是在主数据库上生成该事务的提交或中止WAL记录的时间.

因此,select now()-pg_last_xact_replay_timestamp() as replication_lag对从属设备的此查询将返回一个持续时间,该持续时间表示当前时钟与从复制流应用的最后一个WAL记录的时间戳之间的时间差.

请注意,如果主服务器没有接收到新的突变,则不会传输WAL记录,并且以这种方式计算的延迟将增长,而实际上并不是复制延迟的信号.如果主控器或多或少存在连续突变,则它将连续地传输WAL,并且上述查询是对主设备上的更改的时间延迟的精确近似,以实现从设备上的实现.精确度显然会受到两台主机上系统时钟严格同步的影响.

  • 关于时钟同步的注意事项至关重要。没有 NTP 守护进程运行意味着您可能没有相同的时钟。这只是帮助我解决了一个不断下降的从属问题,实际上,这只是时钟漂移。除了时间作为完整性检查之外,查看您后面有多少字节很有用。 (2认同)

Cra*_*ger 19

您可以非常轻松地从主端获取字节延迟,pg_xlog_location_diff以便将主设备pg_current_xlog_insert_locationreplay_location后端的pg_stat_replication条目进行比较.

这仅适用于在主服务器上运行时.您无法从副本执行此操作,因为副本不知道主服务器的前面有多远.

此外,这不会告诉你几秒钟的滞后.在当前(至少9.4)PostgreSQL版本中,没有与提交或WAL记录相关联的时间戳.所以没有办法告诉给定的LSN(xlog位置)多久以前.

在当前PostgreSQL版本上获得副本延迟的唯一方法是让外部进程update定期提交到专用时间戳表.因此,您可以current_timestamp在副本上比较副本中可见的该表中最新条目的时间戳,以查看副本的落后程度.这会创建额外的WAL流量,然后必须将其保存在PITR(PgBarman或其他)的归档WAL中,因此您应该将增加的数据使用与您需要的滞后检测的粒度进行平衡.

PostgreSQL 9.5可能会添加提交时间戳,希望能够让您了解给定提交的持续时间,以及因此在挂钟时间内复制品的落后程度.

  • 谢谢.我使用pg_last_xact_replay_timestamp()解决了问题; (6认同)

iur*_*niz 14

PostgreSQL 10 或更高版本(答案)

对于postgresql 10或更高版本(pg_last_xlog_receive_location()该版本中不存在函数和其他函数),我使用这个:

SELECT
  pg_is_in_recovery() AS is_slave,
  pg_last_wal_receive_lsn() AS receive,
  pg_last_wal_replay_lsn() AS replay,
  pg_last_wal_receive_lsn() = pg_last_wal_replay_lsn() AS synced,
  (
   EXTRACT(EPOCH FROM now()) -
   EXTRACT(EPOCH FROM pg_last_xact_replay_timestamp())
  )::int AS lag;
Run Code Online (Sandbox Code Playgroud)

如果您在 master 上运行此查询,结果将是:

 is_slave | receive | replay | synced | lag 
----------+---------+--------+--------+-----
 f        |         |        |        |    
(1 row)
Run Code Online (Sandbox Code Playgroud)

如果您在同步从站上运行此查询,结果将类似于:

 is_slave |  receive  |  replay   | synced | lag 
----------+-----------+-----------+--------+-----
 t        | 0/3003128 | 0/3003128 | t      | 214
(1 row)
Run Code Online (Sandbox Code Playgroud)

如果您在未同步的从属设备上运行此查询,结果将类似于:

 is_slave |  receive  |  replay   | synced | lag 
----------+-----------+-----------+--------+-----
 t        | 0/30030F0 | 0/30023B0 | f      | 129
(1 row)
Run Code Online (Sandbox Code Playgroud)

注意: (seconds) 在这里有特殊含义(与//从视图中看lag不一样),并且仅当列为 时才有用,因为表示自上次操作提交以来经过了多少秒。在低流量站点中,该值是无用的。但在高流量站点中,可能(并且将会)几乎是时间,但是如果它的值足够小,则可以认为服务器已同步。replay_lagwrite_lagflush_lagpg_stat_replicationsyncedfalselagsyncedfalselag

因此,为了发现该服务器是否已同步,我检查(按此顺序):

  • IFis_slavef(意味着不是从属设备,可能是主设备,因此它是同步的);
  • IFsyncedt(意味着它是同步从属设备,因此它是同步的);
  • IF(假设适用)lag <= :threshold:(意味着不是同步从站,但它离主站不太远,所以对我来说已经足够同步了)。

如果您想要以秒为单位(包括小数)的滞后,请执行以下操作:

 is_slave | receive | replay | synced | lag 
----------+---------+--------+--------+-----
 f        |         |        |        |    
(1 row)
Run Code Online (Sandbox Code Playgroud)


Ram*_*nan 8

如果您的数据库有频繁写入,则下面的查询非常接近于获得从属延迟

select now() - pg_last_xact_replay_timestamp() AS replication_delay;
Run Code Online (Sandbox Code Playgroud)

下面是一个更精确的查询,用于计算写入次数很少的数据库的复制滞后.如果主设备没有向从设备发送任何写入,则pg_last_xact_replay_timestamp()可以是常量,因此可能无法使用上述查询准确地确定从设备延迟.

SELECT CASE WHEN pg_last_xlog_receive_location() =
pg_last_xlog_replay_location() THEN 0 ELSE EXTRACT (EPOCH FROM now() -
pg_last_xact_replay_timestamp()) END AS log_delay;
Run Code Online (Sandbox Code Playgroud)


shu*_*ikk 6

略有不同版本的正确答案:

postgres=# SELECT
  pg_last_xlog_receive_location() receive,
  pg_last_xlog_replay_location() replay,
  (
   extract(epoch FROM now()) -
   extract(epoch FROM pg_last_xact_replay_timestamp())
  )::int lag;

  receive   |   replay   |  lag  
------------+------------+-------
 1/AB861728 | 1/AB861728 | 2027
Run Code Online (Sandbox Code Playgroud)

只有当"接收"不等于"重播"时,滞后才是重要的.在slave上执行查询


Vao*_*sun 5

截至 10 版:

https://www.postgresql.org/docs/10/static/monitoring-stats.html#pg-stat-replication-view

write_lag 间隔 在本地刷新最近的 WAL 和接收到此备用服务器已写入它(但尚未刷新或应用它)的通知之间经过的时间。如果此服务器被配置为同步备用服务器,这可用于衡量 synchronous_commit 级别 remote_write 在提交时产生的延迟。

flush_lag 间隔 在本地刷新最近的 WAL 和接收到此备用服务器已写入并刷新它(但尚未应用它)的通知之间经过的时间。如果此服务器被配置为同步备用服务器,这可用于衡量 synchronous_commit 级别 remote_flush 在提交时产生的延迟。

replay_lag 间隔 在本地刷新最近的 WAL 和接收到此备用服务器已写入、刷新和应用它的通知之间经过的时间。如果此服务器配置为同步备用服务器,这可用于衡量 synchronous_commit 级别 remote_apply 在提交时产生的延迟。

(格式化我的)

唉,新列似乎只适合同步复制(否则主不会知道确切的延迟)因此异步复制延迟 chack 似乎仍然存在now()-pg_last_xact_replay_timestamp()......