postgres实操

11 阅读4分钟

背景

使用 immich 时某些接口请求频繁出现类似

Unknown error: PostgresError: index "PK_c67bc36fa845fb7b18e0e398180" contains unexpected zero page at block 125

或者是

WARNING:  page verification failed, calculated checksum 37716 but expected 6354

也或者是

error: query failed: ERROR:  invalid page in block 0 of relation base/16384/16731

是的,文件损坏!一度怀疑是 nas 强制断电造成的,在抢救数据的过程中偶然发现容器退出了,看了一下系统日志,一大堆类似

perl[778532]: segfault at 55ee62c27eb0 ip 000055ee62878111 sp 00007ffef16129f0 error 4 in perl[55ee6286c000+1ae000]

这样的日志。

如果使用 vscode 远程,更离谱,会出现一大堆的僵尸进程,然后 systemd 直接就假死,ssh 连不上,运气好连上了,凡是 systemd 托管的进程全都异常,包括 docker

甚至关机重启都做不到!只能强制关机!

偶发性出现 docker compose 无法使用,直接报 core dump

本文目的不是为了去定位解决这个诡异的问题,而是直接怀疑 ubuntu 24.10 这个版本有大问题,准备降级或换 debian,本文主要记录一下怎么去恢复我的数据!

定位问题

首先根据 error: query failed: ERROR: invalid page in block 0 of relation base/16384/16731 这种报错,查询对应的数据库和数据表

SELECT oid, datname FROM pg_database WHERE oid = 16384;
-- 显示对应的数据库为 immich
--  oid  | datname
-- -------+---------
--  16384 | immich
-- (1 row)

使用 \c immich 命令选择 immich 数据库,查询 16731 对应的表

SELECT relname, relkind FROM pg_class WHERE oid = 16731;
--        relname        | relkind
-- ----------------------+---------
--  albums_assets_assets | r
-- (1 row)

好了,就是这个表有问题。因为数据库是跑在 docker 里,很多检查、校验方式都不方便操作,这里仅根据我的操作进行处理。

尝试读取

先试着读取,看看是不是整个表都么得救了

select * from albums_assets_assets limit 10;
-- 刚好有救,证明只有部分数据丢了而已,根据 albums_assets_assets 的字段,使用条件查询尽可能把数据查出来

就这样枯燥乏味的机械操作过后,拿到了大部分的数据,只丢了几个不重要的相册记录,无关紧要。

尝试恢复

噩梦开始啦!整个数据库,截至 1.132.3 版本,总共 41 张表,表跟表之间是有外键约束的!还有触发器!根本没法删表直接导入!而要剔除的数据本身就是损坏的,根本没法操作!再来一次枯燥乏味的机械操作,把每张表数据单独导出来,然后继续枯燥乏味的机械操作,建表建索引,导数据,最后加外键约束和触发器,最后发现只有一张 person 表格和 asset_face 的外键约束有问题。看了一下,提示 asset_face 中存在记录,该记录的外键在 person 中不存在!

???
不存在?
还能不存在的?

删!在 asset_face 表中删掉这个记录之后,容器崩了

???

重启发现 error: query failed: ERROR: invalid page in block 0 of relation base/16384/16731 类似的问题又来了,这次不止一张表!

心灰意冷。。。。

重启大法

systemd 还没崩,还能重启,赶紧先重启了。

重启了发现,pg_dump 竟然能用???

赶紧一发 pg_dump -U postgres -d immich > immich-backup.sql 成功把数据导出。

新建文件夹,新开个容器,把 immich-backup.sql 放进去一顿操作 psql -U postgres -d immich -f immich-backup.sql 恢复,终于,还是出现了外键约束错误,打开 immich-backup.sql,把相关冲突的记录删掉,停容器,删新文件夹,重新构建,再放进去一顿操作。怎么还有!!!就不能一次性报错吗???重复了三四次,终于成功删干净并且恢复成功了,损失几个不记名人脸的数据。

实际上操作不止上述这些,搞了两天,也尝试了很多修复的方法,都不得行,最终只能是将能导出的数据导出重新导入。

疑惑

1、为什么 docker 会莫名其妙崩?还会导致我数据库文件损坏?

2、docker 崩是 systemd 搞的鬼吧?段错误出现之后 docker 基本就不能操作了,再用 vscode 远程,连关机都做不到了,ssh 也连不上。

3、ubuntu 24.10 这个版本有问题吧?

4、最重要的,为什么都有外键约束了,两个表为什么还能存在超越约束的数据啊?这个约束是某个版本更新之后才加上的?可是数据都存在冲突了,约束肯定就定义不了了啊,先有约束再写的数据?更诡异了好吧

结论

谁用新版本系统谁是狗!