背景
使用 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、最重要的,为什么都有外键约束了,两个表为什么还能存在超越约束的数据啊?这个约束是某个版本更新之后才加上的?可是数据都存在冲突了,约束肯定就定义不了了啊,先有约束再写的数据?更诡异了好吧
结论
谁用新版本系统谁是狗!