PostgreSQL 逻辑复制依赖于 WAL 段?

PostgreSQL logical replication depends on WAL segments?

我成功地在 2 个 PG 11 云 VM 之间使用逻辑复制来获取最新数据。但我也尝试发布一些旧表以在数据库之间传输数据,但出现了关于缺少 WAL 段的奇怪错误。

这些较旧的分区包含 5-6 天前的数据。我成功地在主服务器上发布了它们,并在逻辑副本上刷新了订阅。但是现在我在逻辑副本上收到这些奇怪的错误消息:

2019-01-21 15:03:14.713 UTC [17203] LOG:  logical replication table synchronization worker for subscription "mysubscription", table "mytable_20190115" has finished
2019-01-21 15:03:19.768 UTC [18877] LOG:  logical replication apply worker for subscription "mysubscription" has started
2019-01-21 15:03:19.797 UTC [18877] ERROR:  could not receive data from WAL stream: ERROR:  requested WAL segment 000000010000098E000000CB has already been removed
2019-01-21 15:03:19.799 UTC [29534] LOG:  background worker "logical replication worker" (PID 18877) exited with exit code 1
2019-01-21 15:03:24.806 UTC [18910] LOG:  logical replication apply worker for subscription "mysubscription" has started
2019-01-21 15:03:24.824 UTC [18911] LOG:  logical replication table synchronization worker for subscription "mysubscription", table "mytable_20190116" has started
2019-01-21 15:03:24.831 UTC [18910] ERROR:  could not receive data from WAL stream: ERROR:  requested WAL segment 000000010000098E000000CB has already been removed
2019-01-21 15:03:24.834 UTC [29534] LOG:  background worker "logical replication worker" (PID 18910) exited with exit code 1

这让我感到困惑。我试图找到一些信息,但没有找到任何关于逻辑复制的信息,具体取决于 WAL 段。

在那个特定的主服务器上没有流复制运行,我在主服务器和副本服务器上看到的这些错误消息只与逻辑复制连接。

我是不是做错了什么?是否有一些特殊的方式来发布旧数据?对于更新的数据和最新的数据,一切都没有问题。

当然,因为我发布了大约 20 个表,所以副本需要一些时间来处理所有表 - 目前它每次总是处理 2 个。但是我还是不明白为什么要依赖WAL段...非常感谢。

更新: 我试图取消发布和取消订阅这些旧表并再次发布和订阅它们,但对于完全相同的 WAL 段号仍然得到相同的错误消息。

更新 2: 我取消发布和取消订阅那些有问题的表和错误消息已停止,因此它们肯定与逻辑复制有关。会不会是快照引起的?

更新 3: 我刚刚对 WAL 段错误有了额外的奇怪体验 - 我的逻辑副本只有非常小的磁盘,在所有这些摆弄过程中我忘记检查磁盘使用情况。因此逻辑副本上的 postgresql 由于磁盘已满而崩溃。因为我使用 GCE,所以我只是调整了根磁盘的大小,并且在实例重新启动后得到了更多 space。但我也找回了与逻辑复制相关的丢失 WAL 段错误。我在副本上的 postgresql 日志现在充满了这 3 行的序列:

2019-01-22 09:47:14.408 UTC [1946] LOG:  logical replication apply worker for subscription "mysubscription" has started
2019-01-22 09:47:14.429 UTC [1946] ERROR:  could not receive data from WAL stream: ERROR:  requested WAL segment 000000010000099D0000007A has already been removed
2019-01-22 09:47:14.431 UTC [737] LOG:  background worker "logical replication worker" (PID 1946) exited with exit code 1

为什么逻辑复制依赖于WAL段?

感谢 pgsql-general 邮件列表上的聪明人,我发现了问题所在。

  1. 逻辑复制确实依赖于 WAL 段 - https://www.postgresql.org/docs/11/logical-replication-architecture.html - 使用 WAL 段分发更改 - 这就是为什么参数 "wal_level" 必须设置为 "logical"大师.

  2. 我的 WAL 段问题是这些情况的组合:

    • 我试图一起发布和订阅我们所有巨大的 tables - 为了解释我们每天有大约 5 亿条记录,最大的 table 每天有约 30 GB 的分区,其他的 1 - 5 GB
    • PostgreSQL 在这种情况下会创建快照,并在激活订阅后开始将数据从快照传输到副本。只有在整个快照传输完成后,walsender 才会开始发送 WAL 日志以获取最新更改
    • 因为我一次发布了大约 200 GB 的数据几天,你可以想象传输花费了很长时间 - 对于传输,创建了 2 个新的逻辑复制槽,并使用 2 个 walsender 将数据传输到副本。
    • 它通常运行良好,但我们有紧急 cronjob,它删除太过时的 WAL 日志,因为在过去我们遇到过几乎满磁盘的问题。这就是我遇到的问题——紧急 cronjob 删除了尚未传输到副本的 WAL 段。所以通常需要有足够的磁盘 space 才能存储比正常情况下多得多的 WAL 日志。我们以前没有 - 但我改变了它。
  3. pgsql-general 的 Jeremy Finzel 建议我实际上应该使用不同的方式从主服务器复制数据 - 一次只发布和订阅一个 table 并给副本时间同步数据。我这样做了,现在逻辑复制就像一个魅力...