首页 > 解决方案 > 由于旧的 walsender 进程,pg_create_logical_replication_slot 无限期挂起

问题描述

我正在测试 2 个 PostgreSQL 11 数据库之间的逻辑复制以用于我们的生产(由于这个答案,我能够设置它 - PostgreSQL logical replication - create subscription hangs)并且效果很好。

现在我正在测试可以在生产数据库上自动设置它的脚本和程序,但是我遇到了逻辑复制槽的奇怪问题。

由于设置中的一些更改需要重新启动,我不得不重新启动逻辑副本——这当然也可能在将来发生在副本上。但是 master 上的逻辑复制槽没有断开连接,并且对于某些 PID 仍然处于活动状态。

我放弃了对 master 的订阅(我仍然只是测试)并尝试使用新的逻辑复制槽重复整个过程,但我面临着奇怪的情况。

我无法使用新名称创建新的逻辑复制槽。在旧的逻辑复制槽上运行的进程仍处于活动状态并显示wait_event_type=Lockwait_event=transaction

当我尝试使用pg_create_logical_replication_slot创建新的逻辑复制槽时,我遇到了类似的情况。新插槽已创建 - 我在 pg_catalog 中看到它,但对于发出此命令的会话的 PID,它被标记为活动,并且命令无限期挂起。当我检查进程时,我可以看到这个命令以相同的等待值锁定/事务处于活动状态。

我试图在 postgresql.conf 中激活参数“lock_timeout”并重新加载配置,但它没有帮助。

杀死旧的挂起进程很可能会导致整个 postgres 崩溃,因为它是“walsender”进程。它在进程列表中仍然可见,副本的 IP 状态为“idle wating”。

我试图找到一些可以帮助我强制 postgres 停止这个 walsender 的参数。但是设置 wal_keep_segments 或 wal_sender_timeout 并没有改变任何东西。我什至试图停止复制更长的时间 - 没有效果。

有没有办法在不重新启动整个 postgres 的情况下解决这种情况?就像强制 walsender 超时或事务锁定等...

因为如果在生产中发生这样的事情,我将无法使用重新启动或任何其他“蛮力”。谢谢...

更新: “Walsender”进程在一段时间后“消失”,但日志没有显示任何关于它的信息,所以我不知道它到底是什么时候发生的。我只能猜测它取决于 tcp_keepalives_* 参数。Debian 9 的默认值为 2 小时以保持空闲进程。所以我尝试在 postgresql.conf 中设置这些参数,并将在以下测试中看到。

标签: postgresql-11logical-replication

解决方案


奇怪的是,今天一切正常,没有任何问题,无论我如何尝试模拟昨天的问题,我都做不到。可能涉及的云数据中心存在一些网络通信问题——我们在连接到其他数据库时也遇到了一些偶尔的超时。

所以我真的不知道答案,除了“等到 master 上的 walsender 进程死亡”——这很可能受到 tcp_keepalives_* 设置的影响。因此,我建议在 postgresql.conf 中将它们设置为一些合理的值,因为 OS 上的默认值通常太大。

实际上,由于类似的问题,我们在大型分析数据库(在 PostgreSQL 和 OS 上设置)上使用它。在某些情况下,Golang 和 nodejs 程序计算统计数据时无法识别数据库会话已结束或消失,并且在 2 小时后操作系统结束连接之前一直挂起(Debian 上的默认设置)。所有这一切似乎总是与网络通信问题有关。使用适当的 tcp_keepalives_* 设置,在出现问题时反应会更快。

旧的 walsender 进程在 master 上死掉后,您可以重复所有步骤,它应该可以工作。所以看起来我昨天运气不好...


推荐阅读