无法从 WAL 流接收数据:错误:请求的 WAL 段已被删除

rsm*_*thy 7 postgresql postgresql-9.6 patroni

配置:Postgres 9.6,具有 3 个集群节点。db1 是主服务器,db2 和 db3 是副本服务器。WAL 文件使用自定义工具存档在 AWS S3 中pgrsync。集群由守护神管理。并在所有节点上正确配置archive_commandrestore_command

模拟:在 db1 上,执行大量写入(例如真空大表),然后通过 停止 db1 sudo systemctl stop patroni。db3 成为新的领导者。db2 请求更多 WAL 文件,这些文件是通过 AWS S3 的正确恢复命令获取的,成为 db3 的副本。

现在,通过( sudo systemctl start patroni)再次启动db1。但是 db1(旧的领导者和新的副本)永远不会作为副本出现并给出错误消息:

无法从 WAL 流接收数据:错误:请求的 WAL 段 0000002400053C55000000AE 已被删除。

此错误消息由 db3(领导者)报告,而 db1 仅记录该消息。

那么,让我们看看时间表。最初 db1 位于时间线 35 (0x23) 并写入以下文件进行存档:

0000002300053C55000000AE   (TL is 23 and archive at 53C55/AE)
..
0000002300053C5600000043   (TL is 23 and archive at 53C56/43)
Run Code Online (Sandbox Code Playgroud)

db1 此时已停止。db3 的日志显示:

received promote request
redo done at 53C56/A3FFC8C0
selected new timeline ID: 36
database system is ready to accept connections
Run Code Online (Sandbox Code Playgroud)

db3 将以下文件复制到存档中

00000024.history
0000002300053C56000000A3.partial
0000002400053C56000000A3
0000002200053C55000000AE
Run Code Online (Sandbox Code Playgroud)

当 db3 成为领导者时,db2 启动进程成为 db3 的副本(它成功成为),以下是日志摘要:

restored log file "00000024.history" from archive
restored log file "0000002300053C55000000AE" from archive
restored log file "00000023.history" from archive
redo starts at 53C55/AE0001A8
restored log file "0000002300053C55000000AF" from archive
...
restored log file "0000002300053C5600000042" from archive
Retrieving 0000002300053C5600000043 to pg_xlog/RECOVERYXLOG FAILED  (log by pgrsync)
...
Retrieving 0000002300053C56000000A2 to pg_xlog/RECOVERYXLOG FAILED
restored log file "0000002400053C56000000A3" from archive
consistent recovery state reached at 53C56/A3FFE900
Run Code Online (Sandbox Code Playgroud)

db1 现已启动,日志如下:

LOG: database system was interrupted while in recovery at log time 2021-01-28 04:08:01 UTC 
HINT: If this has occurred more than once some data might be corrupted and you might need to choose an earlier recovery target
LOG: invalid record length at 53C55/AE0001E0: wanted 24, got 0
LOG: started streaming WAL from primary at 53C55/AE000000 on timeline 36
FATAL:  could not receive data from WAL stream: ERROR:  requested WAL segment 0000002400053C55000000AE has already been removed
... and repeats this over and over
Run Code Online (Sandbox Code Playgroud)

注意事项:

  1. 0000002400053C55000000AE从未被任何 Postgres 节点写入档案。0000002300053C55000000AE旧的领导者(db1)在停止之前复制了存档(注意:0023,而不是0024)。
  2. 新的领导者(db3)被复制0000002200053C55000000AE(注意:0022,而不是0024)
  3. max_wal_size在所有节点上设置为 1024。
  4. db3 成为新的领导者后,节点上几乎没有任何活动。db3 仅每 10 分钟(=600 秒)写入一次 WAL 文件archive_timeout

问题:

  1. 配置中是否有任何错误导致旧领导者请求 WAL 段,而新领导者没有?
  2. 如何在这种状态下恢复旧的领导者(db1),而不必擦除并重新开始?

有大量可用磁盘空间。问题可以随意模拟。已尝试pg_rewind过旧的主要,指向新的主要。它只是说它已经在同一时间线上(不是确切的文字)。注意:这不是错误消息。但即使在那之后,在启动 Postgres 时它仍然显示相同的错误。

我们是 2019 年 6 月 9 日。就在几天前,9.6.21(以及最后一个 9.5.x 版本)发布,它准确地指出了此特定问题的修复(修复 WAL 读取逻辑,以便备用数据库可以正确处理时间线切换。此问题可能会出现错误就像“请求的 WAL 段已被删除”。)。然而,即使升级到9.6.21后,我们仍然存在同样的问题。

小智 1

我们遇到了类似的情况,最终从当前的主要初始化。这里有一个讨厌的错误。因此,为了安全起见,我的建议是重新实例化奴隶。(直到错误修复到位)如果您有一个很好的可重现案例,那么将其记录下来会有所帮助,以便可以对其进行研究,并且运气好的话可以在代码中修复。报告错误:https ://www.postgresql.org/docs/current/bug-reporting.html

PostgreSQL 12.3、11.8、10.13、9.6.18 和 9.5.22 发布! 此错误已在 9.5.22、9.6.18、10.13、11.8 和 12.3 中修复:避免在崩溃恢复期间过早回收 WAL 段 (Jehan-Guillaume de Rorthais)

在崩溃恢复期间准备归档的 WAL 段可能会在未归档的情况下被回收。