使用Docker时,触发了PANIC:无法找到有效的检查点记录。

13

我在努力理解Docker,但在此过程中,我的应用程序的PostgreSQL数据库似乎出现了损坏。

我正在使用Docker Swarm启动我的应用程序,但在PostgreSQL容器中不断收到以下错误:

    2021-02-10 15:38:51.304 UTC 120 LOG:  database system was shut down at 2021-02-10 14:49:14 UTC
    2021-02-10 15:38:51.304 UTC 120 LOG:  invalid primary checkpoint record
    2021-02-10 15:38:51.304 UTC 120 LOG:  invalid secondary checkpoint record
    2021-02-10 15:38:51.304 UTC 120 PANIC:  could not locate a valid checkpoint record
    2021-02-10 15:38:51.447 UTC 1 LOG:  startup process (PID 120) was terminated by signal 6
    2021-02-10 15:38:51.447 UTC 1 LOG:  aborting startup due to startup process failure
    2021-02-10 15:38:51.455 UTC 1 LOG:  database system is shut down

起初,我试图通过进入文件系统中的挂载驱动器来修改容器中的 pg_hba.conf 文件,该驱动器位于

 /var/lib/docker/volumes/postgres96-data-volume/_data

然而,每次我重启容器后,对于 pg_hba.conf 的更改都会被还原。因此今天早上,我在挂载文件夹中添加了一个名为test的虚拟文件,并重新启动容器,期望该文件将被删除,以获得一种视觉验证:重启容器会自动将该挂载点下的所有内容替换为其原始格式。但当我再次重启时,就开始出现阻止我的应用程序启动的错误消息了。

我删除了 test 文件并再次重启了容器,但错误消息仍然存在。

我看过许多解决方案,但我的问题更多地是想了解为什么添加一个文件会导致这种情况?我添加了一个文件,导致我的挂载卷已经被损坏了吗?

谢谢。


我不知道你搞砸了什么,但错误意味着数据库崩溃并且没有正确关闭,在重新启动时无法找到事务日志文件,因此无法恢复。这已经无法修复。此外,错误消息来自旧版PostgreSQL。请使用当前软件。 - Laurenz Albe
4个回答

14

警告

针对那些准备使用被接受答案的解决方案的人,这里有一个警告:

被接受的答案中的解决方案要求删除docker卷,这意味着PostgreSQL实例中的所有数据都将丢失!!!

如果您想保留数据库实例的数据,请参考我的答案here

我遇到同样错误的情境

我也使用docker swarm部署容器,最近在尝试将postgres db扩展为创建两个副本时遇到了这个问题,这两个副本都指向同一个物理卷(使用docker挂载,使用NFS共享)。 这是为了使数据在两个副本之间保持同步。 但这导致我遇到了和您一样的错误

PANIC: could not locate a valid checkpoint record

我的发现

首先,数据库卷没有损坏,只是交易WAL损坏或者失去了一致性。我进行了大量的研究。我发现这个错误可能发生在以下两种情况下:

  1. 数据库正在执行一个活动事务,但突然由于某些错误关闭。在这种情况下,WAL告诉数据库当它意外关闭时应该做什么。然而,如果数据库在WAL更新期间关闭,则WAL可能反映实际执行但具有不正确执行信息的某些事务。这导致了DB数据与WAL之间的不一致或者是一个损坏的交易日志,从而引发了检查点错误。

  2. 您创建了指向同一个卷的多个db副本。考虑我面临的2个副本的情况。当两个副本同时尝试在同一个db卷上执行事务时,交易WAL失去一致性,因为存在两个同时的检查点。由于无法确定要考虑哪个检查点为正确的检查点,所以数据库无法执行任何其他事务。如果两个容器(不一定是副本)指向PG_DATA的相同挂载路径,也可能发生这种情况。

最终,db无法启动。由于db抛出了一个错误并关闭了容器,因此容器无法启动。

您可以重置WAL来解决这个问题。重置WAL时,尚未在DB中执行的事务数据将会丢失。但是,已经写入和处理的数据将被保留。


0

我专门创建了一个账户来回答这个问题。像上面palc回复的那样,任何其他答案都会删除您的数据。即使是当前被接受的答案也是如此。

我在Kubernetes上遇到了同样的问题,所以我想解释一下我是如何解决这个问题的。它也适用于docker。

  1. 将部署规模缩小为0或仅停止Pod。
  2. 更改入口点如下:
    Entry point: /bin/sh
    Arguments: -c 'sleep 3600'
  1. 将部署规模缩小到1,或重新启动Pod。

  2. 在Pod中获取一个shell。使用/bin/sh

  3. 成为“postgres”

    su - postgres

  4. 修复WAL。<directory>是您数据的位置。我的位置是

    /var/run/postgres/data /usr/lib/postgres/13/pg_resetwal <directory>

  5. 将部署规模缩小到0,删除entrypoint/arguments,并将其重新缩放到1。


0
为解决此错误,您可以尝试以下步骤:
停止并删除现有的 PostgreSQL 容器:
```bash docker stop docker rm ```
删除旧的 PostgreSQL 数据目录,通常位于 `/var/lib/postgresql/data`。这将删除所有数据库数据,请确保在执行此操作之前备份任何重要数据。
使用新的数据目录创建一个新的 PostgreSQL 容器:
```bash docker run --name -d postgres ```

-3

这个错误意味着Postgres卷已经损坏。当两个容器同时尝试连接到同一个卷时,就会发生这种情况。有关稍微更多的信息,请参见此答案。不确定修改文件如何损坏驱动器。您需要删除并重新创建卷。要执行此操作,可以:

$ docker stop <your_container_name> # stops a running container
$ docker image prune # removes all images that are not attached to a container
$ docker volume ls # list out active volumes
$ docker volume rm <volume_name> # Remove the volume that's corrupted

我需要运行以上代码来停止一个容器,清理一些没有附加到任何容器的镜像,最后删除那个存储有损坏数据的有问题的卷。


2
我给这个点了踩,因为你没有清楚地警告这会导致数据丢失。 - Martin von Wittich

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