我写这篇帖子是关于一个导致我每日备份失败的 PostgreSQL 表缺失块错误。我设法解决了这个问题,并想在此列出我使用的方法,以防它能帮助到其他遇到此问题的人。这绝不是解决 PostgreSQL 缺失块错误的正确指南或专业说明,因为我不是专家,而且是在不太了解的情况下进行的,但最终奏效了。
我备份时遇到的错误:
pg_dump: error: Dumping the contents of table "stylesheet_cache" failed: PQgetResult() failed.
pg_dump: error: Error message from server: ERROR: missing chunk number 0 for toast value 1903804 in pg_toast_22663
pg_dump: error: The command was: COPY public.stylesheet_cache (id, target, digest, content, created_at, updated_at, theme_id, source_map) TO stdout;
所以问题出在 stylesheet_cache 表上,错误是:ERROR: missing chunk number 0 for toast value 1903804 in pg_toast_22663。
我使用的是 Discourse in Docker,我所做的如下:
ssh into the server
cd /path/to/discourse
./launcher rebuild app
su postgres -c "psql discourse"
进入 PostgreSQL 后,我尝试 REINDEX 表,希望能解决问题。
discourse=# select reltoastrelid::regclass from pg_class where relname = 'stylesheet_cache';
reltoastrelid
-------------------------
pg_toast.pg_toast_18396
(1 row)
REINDEX table stylesheet_cache;
REINDEX table pg_toast.pg_toast_18396;
VACUUM analyze stylesheet_cache;
再次尝试备份,仍然失败,所以我不得不继续寻找损坏。
我使用以下命令计算了表中的总行数:
select count(*) from stylesheet_cache;
我得到了 2260 行的计数。
我开始寻找损坏的确切行并删除它,我假设 stylesheet_cache 并不是一个会真正破坏我整个数据库的东西。正如我提到的,我不是专家,所以也许我冒了太大的风险,请在执行此操作时小心,因为你可能会弄乱你的数据库。
我使用了 LIMIT 和 OFFSET 查询来查找损坏的行:
select * from stylesheet_cache order by id limit 100 offset 0;
我调整了 offset 和 limit,直到出现“Missing chunk…”错误,然后缩小范围到 LIMIT 1 和 offset 损坏的行。在我的例子中,有 5 行损坏。
你可以使用一个 shell 脚本来更轻松地找到行,我选择了手动方式,这花费了一些时间,但你可以使用这个:
#!/bin/sh
j=0
while [ $j -lt 2260 ]
do
psql -U postgres -d discourse -c "SELECT * FROM stylesheet_cache LIMIT 1 offset $j" >/dev/null || echo $j
j=$(($j+1))
done
我使用以下命令查找损坏行的 ID:
select id from stylesheet_cache order by id limit 1 offset 450;
id
----
11498
所以我的损坏行的 ID 是 11498。
我使用以下命令删除了该行:
delete from stylesheet_cache where id = 11498;
删除损坏的行后,我再次 REINDEX:
REINDEX table stylesheet_cache;
REINDEX table pg_toast.pg_toast_40948;
VACUUM analyze stylesheet_cache;
然后再次尝试备份,这次成功了。我参考了这份 PostgreSQL 恢复说明:Postgres error: Missing chunk 0 for toast value in pg_toast · GitHub
免责声明:这不是专家意见,因此如果你遇到类似的缺失块损坏并尝试修复它们,请谨慎操作。