Docker postgres 无效的主检查点记录

phe*_*per 7 postgresql docker

我一直在尝试让 postgres 在 Docker(在 Windows 上)中运行并具有持久数据存储,并认为我终于拥有了它,但现在当我尝试启动容器时,出现以下错误:

LOG:  invalid primary checkpoint record
LOG:  invalid secondary checkpoint record
PANIC:  could not locate a valid checkpoint record
Run Code Online (Sandbox Code Playgroud)

这是我启动并运行容器的开始:

docker volume create ct_data
docker run --name postgres_ct -v ct_data:/var/lib/postgresql/data -p 5432:5432 postgres
Run Code Online (Sandbox Code Playgroud)

然后,我使用 pgAdmin 连接到它,创建一个新表,并使用恢复选项导入 postgres 转储文件。数据加载没有问题。我使用与上面相同的卷启动了第二个容器,但使用不同的名称和端口号来测试它,并且我能够连接,因此我将其关闭。

Now, an hour later, I found my original container was stopped automatically so I tried to start it back up and got the errors above. This is my first attempt at using Docker, so it's very possible I'm missing something simple here.

pal*_*alc 10

这篇相关文章接受的答案要求删除docker 卷,这意味着PostgreSQL 实例中的所有数据都将丢失

我最近在存储了数月数据的环境中遇到了同样的问题。因此,删除/删除卷是(非常非常)最后的手段。

我遇到了这个答案,它要求重置事务预写日志(WAL)。这适用于数据库作为应用程序安装而不是作为容器运行的场景。但是,对于 docker,容器本身由于以下错误而无法部署

PANIC:无法找到有效的检查点记录

解决方案

这种情况下的解决方案是对 postgres 映像使用docker run命令,并在正确的 PGDATA 路径(您之前配置的)上安装相同的物理卷,然后直接登录到 bash shell。

docker run -it -v /data/postgres_data:<PGDATA_path> postgres:14 /bin/bash
Run Code Online (Sandbox Code Playgroud)

如果您没有更改,则<PGDATA_path>默认为默认值。/var/lib/postgresql/data如果您使用的是 docker 卷,则需要从卷列表中找出 docker 卷名称:docker volume ls。获取卷名称,然后使用docker run如下所示。

docker run -it -v <docker_volume_name>:<PGDATA_path> postgres:14 /bin/bash
Run Code Online (Sandbox Code Playgroud)

获得容器的 shell 后,您现在可以使用以下命令重置 WAL

# Postgres >= 10
pg_resetwal <PGDATA_path>

# Postgres < 10
pg_resetxlog <PGDATA_path>
Run Code Online (Sandbox Code Playgroud)

如果需要,请使用该-f选项。有关更多详细信息,请参阅PostgreSQL 文档。pg_resetwal

docker-compose现在,退出容器的 shell 并使用/重新部署容器(docker stack无论您使用的是哪个),您将成功恢复数据库,同时保留所有数据。

笔记

  1. 一些数据仍然可能会丢失,特别是在WAL没有达成共识的地方。
  2. 一些依赖于数据库的应用程序可能会引发进一步的错误,例如“数据库日志已重置,未找到插入的数据”。在这种情况下,您将必须重置这些应用程序的写入头。
  3. 请访问我的答案以了解何时/为何会发生这种情况。


phe*_*per 3

感谢@Matt 的帮助,我知道发生了什么。当我同时连接两个容器时,该卷(又名 postgres 数据库)就损坏了。

虽然可以允许多个容器连接到单个数据库容器,但不能通过共享卷。您需要创建一个新容器来运行 postgres 守护进程,然后其他容器可以通过 tcp 套接字连接到它。有关如何执行此操作的更多信息,请阅读文档