postgresql , 10.0 , 时间度量备库延迟 , pg_stat_replication
pg_stat_replication视图中有4个字段记录了从备库反馈的wal位点。如下:
通过计算,我们可以得到当前备库与主库在4个维度的延迟(wal字节数)情况。
使用以上方法,能查询的延迟是字节形式反馈的。
那么如果要转换为时间形式,目前没有很好的方法,除非从wal文件中读取对应lsn record的时间信息。
10.0将在pg_stat_replication视图中新增几个字段,用于表示时间上的延迟(write_lag, flush_lag and replay_lag)。
1. 主库开辟了一块buffer,同时采样并记录主库flush wal record的lsn位置以及对应的时间。
2. 实际上,目前记录的并不是flush wal record的lsn位置以及对应的时间,而是wal sender lsn的时间,所以目前的代码,我们应该理解为延时是从发送lsn到备库write,flush,replay三个阶段的延时。
而不是主库flush lsn到备库write,flusn,replay的延时。
当主备wal的发送延迟不大时,这个是比较准确的,当主备的wal发送延迟较大时,这个就不准了。
代码如下。
3. 每个wal sender都会维护一个lagtracker。
4. 备库wal receiver进程会feedback 备库的wal write, flush, replay的lsn位点,主库的wal sender进程收到feedback后,通过lagtrackerread(记录在buffer中的lsn+时间戳,以及当前时间),得到备库的延迟。
代码如下
以上仅适用于物理复制。
对于逻辑复制,decode plugin需要负责开发对应的延迟存储和获取的代码。
目前10.0的做法是最小化的代码改动量,实现一个近似的时间度量的主备延迟。弊端是,当wal sender断开后或者发送存在较大延迟是,这种方法统计得到的备库时间的延迟偏差就会比较大。
其他的方法思考,比如在wal中记录一些wal插值(比如通过wal custom接口,记录lsn位置和时间), 因为commit\rollback wal record以及wal插值都记录了时间,备库可以直接在解析时得到lsn以及时间,所以可以直接反馈write, flush, replay的时间。通过这种方法,主库不需要开辟wal来跟踪lsn的时间。这种方法得到的时间相对比较精确,但是会增加日志写入量,同时可能需要修改流复制协议。
这个patch的讨论,详见邮件组,本文末尾url。
postgresql社区的作风非常严谨,一个patch可能在邮件组中讨论几个月甚至几年,根据大家的意见反复的修正,patch合并到master已经非常成熟,所以postgresql的稳定性也是远近闻名的。
<a href="https://git.postgresql.org/gitweb/?p=postgresql.git;a=commit;h=6912acc04f0bbcfdb799a120618507601e862490">https://git.postgresql.org/gitweb/?p=postgresql.git;a=commit;h=6912acc04f0bbcfdb799a120618507601e862490</a>