在事务期间检索Postgres数据库的LSN

4
在Postgres中,我正在进行一项REPEATABLE READ事务,以便在事务开始时获取数据库的一致视图。我想知道从此事务的角度来看LSN,以便我可以同时在此LSN上设置复制插槽,这样一旦完成事务,我就可以在LSN上设置逻辑复制并接收事务开始后对数据库的所有更新。
我的期望是,在事务内部(其他连接正在进行更新等情况下),LSN不会改变,然而在事务中多次调用pg_current_wal_lsn却导致每次都得到不同的LSN。
有没有方法可以确定从事务的角度来看最后一个LSN?
为了更好的理解背景,我想在一个数据库上设置逻辑复制,但必须先处理在设置复制插槽之前存在于数据库中的数据。 我必须假设之前的WAL段已被清除,因此我不希望通过逻辑复制在数据库中看到所有数据,并且需要一种方式首先处理现有数据,然后再传输所有数据。希望这样说起来有意义。
谢谢。
1个回答

5
REPEATABLE READ 事务中固定的是快照,而不是 WAL 位置,因为这样的事务可以执行数据修改。此快照确定其可见的行版本。
快照包括最小的事务 ID(事务可以看到由早期事务创建的任何行)、最大的事务 ID(事务不能查看比它更新的事务)和所有并发事务 ID 的列表。
如果您有一个 REPEATABLE READ READ ONLY 事务,则查询在获取快照时插入 WAL 的位置是有意义的。
SELECT pg_current_wal_insert_lsn();

作为事务中的第一条语句。

但是,存在竞态条件:首先 PostgreSQL 对快照进行拍摄,然后执行查询。在这些时间之间,并发事务可能会执行数据修改,这些修改对于快照不可见,但是在从函数获得的 LSN 之前。

解决方案是使用逻辑解码。正如文档所说:

当使用流复制接口(参见CREATE_REPLICATION_SLOT)创建新的复制槽时,导出快照(参见第9.27.5节),该快照将显示所有更改都包括在更改流中之后数据库的状态。可以使用SET TRANSACTION SNAPSHOT来读取创建插槽时数据库的状态来使用此事务创建新的副本。然后可以使用插槽内容更新该时段数据库的状态,而不会丢失任何更改。

所以你需要反过来做:首先创建逻辑复制槽,然后启动一个 REPEATABLE READ事务并设置其快照,以便它查看正确的数据。


谢谢!这个完美地运行了。 - Adam Kamor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接