暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

PostgreSQL 17新特性:pg_wal_replay_wait 介绍

作者:樊智辉

我们可以为PostgreSQL主数据库创建一个备用实例,主实例与备用实例之间的同步通过WAL(预写日志)实现。备用实例既作为灾难恢复措施,也能处理一些只读查询。然而,由于主备之间同步固有的延迟,对备用实例的读请求可能无法访问到最新数据,这在使用其进行只读查询时带来挑战。

解决方案1:synchronous_commit + synchronous_standby_names

我们可以将synchronous_commit设置为remote_apply,并将synchronous_standby_names设置为’standby_name1’。这种配置确保一个事务在主实例上完成提交之前已成功复制到’standby_name1’。因此,任何在主实例上成功的写操作会立即在备用实例上可见。这种方法的缺点是对主实例写性能的影响显著,如果’standby_name1’变得不可用,也会影响到主实例的可用性。同时这也会和 ANY 关键字有语义冲突,因为一旦用了ANY 关键字,我们无法确保真正同步的standby 就是处理我们请求的standby.

解决方案2:pg_current_wal_flush_lsn() + pg_last_wal_replay_lsn

在主实例上提交一个事务(txn1)后,我们获取一个表示WAL写入位置的flush LSN(标记为flushLsn1)。应用程序随后连接到备用实例并执行pg_last_wal_replay_lsn来确定备用实例的恢复位置。如果备用实例的LSN超过了先前获取的LSN,这表明来自txn1在主实例上的写入现在在备用实例上可见。但这并不能保证备用实例拥有绝对最新的数据,因为在此之后可能还提交了新的事务。尽管如此,这可能已经满足了大部分的业务需求。其缺点是应用程序必须【持续查询】备用实例以获取其重播LSN,这需要额外的代码逻辑,并由于多次网络交互引入了性能开销。

解决方案3:pg_current_wal_flush_lsn() + pg_wal_replay_wait


这个解决方案与解决方案2的功能相同,但简化了应用程序代码。应用程序无需持续轮询,应用程序只需调用一次pg_wal_replay_wait即可。pg_wal_replay_wait 会接受一个lsn参数, 当standby回放到制定lsn的时候返回。该函数也可以指定一个超时值,如果将超时设置为0,则该函数将无限期等待,直到满足所需条件。如果超时为正数且在指定时间内未达到所需的LSN,则数据库将引发ERROR。该方案依然存在的缺陷是:如果standby 延迟时间太久,pg_wal_replay_wait 会等待的时间也会很久。


文章转载自开源软件联盟PostgreSQL分会,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论