暂无图片
PostgreSQL数据库toast表数据损坏处理
最近更新:2023-10-26 10:34:46

一、pg_statistic的toast表数据损坏

问题现象

在安装插件的时候使用\dx元命令的时候,突然发现报了一个错误:

postgres=# \dx
ERROR:  missing chunk number 0 for toast value 32789 in pg_toast_2619

根据提示来看,主表字段还留存着Toast Pointer,但Toast表中已经没有对应的Chunk条目,怀疑toast表存在损坏或者缺失数据。

toast表的表名是字符串"pg_toast"与表的oid拼接而成,根据这个pg_toast_2619的2619的oid,可以定位到是pg_statistic的表。

postgres=# select 2619::regclass;
   regclass   
--------------
 pg_statistic
(1 row)
postgres=# select * from pg_statistic;
ERROR:  missing chunk number 0 for toast value 32789 in pg_toast_2619
postgres=# 

问题原因

对应toast表的数据可能存在损坏。

处理方法

需要定位损坏的行的位置,然后可以删除有问题的行。因为pg_statistic的toast数据是更新统计信息的时候插入的,损坏后可以直接清理。vacuum analyze后会重新生成。

其他系统表损坏比较建议建议zero_damaged_pages设置为on来跳过损坏的块,然后备份业务数据,之后恢复到一个新的环境。

可以暂时先做下简单的修复,看是否能解决问题,可能执行过程会出现报错:

postgres=# REINDEX TABLE pg_toast.pg_toast_2619;
postgres=# REINDEX TABLE pg_statistic;
postgres=# VACUUM ANALYZE pg_statistic;

可以使用如下的存储过程

 DO $$
DECLARE
  rec record;
BEGIN
FOR rec in SELECT * FROM pg_statistic LOOP
  raise notice 'Parameter is: %', rec.ctid;
   raise notice 'Parameter is: %', rec;
END LOOP; 
END;
$$
LANGUAGE plpgsql;

结果如下:

NOTICE:  Parameter is: (0,1)
NOTICE:  Parameter is: (1255,28,f,0.9830149,1294,-0.016985118,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,,,,,,,,,,)
NOTICE:  Parameter is: (0,2)
NOTICE:  Parameter is: (1255,29,f,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,,,,,,,,,,)
NOTICE:  Parameter is: (0,3)
......