
【摘要】
compressed data is corrupt产生的原因大体分为二方面,第一就是硬件问题导致的corrupt,第二种有可能是数据库系统、操作系统在使用当中由于本身的bug或者操作的不恰当导致的问题,具体导致此问题的原因请参照以下说明:
Remember that most corruption is caused by hardware issues:
RAID controllers with faulty worn out battery backup, and anunexpected power loss
Hard disk drives with write-back cache enabled, and an unexpectedpower loss
Cheap SSDs with insufficient power-loss protection, and anunexpected power-loss
Defective RAM
Defective or overheating CPU(s)
Other causes can be:
Database systems configured with fsync=off and an OS crash or powerloss
Filesystems configured to use write barriers plus a storage layerthat ignores write barriers. LVM was a particular culprit but full barriersupport was added by Liunx 2.6.33-rc1.
PostgreSQL bugs
Operating system bugs
Admin error
directly modifying Postgres data-directory contents
faulty fail-over procedures like rsync'ing without pg_start_backup
【关键词】
操作系统引导 pg_dump copy PG Database corrupt
1.问题的提出
此问题是由于客户现场做逻辑备份的时候出现了pg_dump ERROR: compressed data is corrupt,通过报错的详细信息可以发现是数据库系统中的业务数据表在转储的时候corrupt了,既然已经知道了产生此问题的对象了,那么也方便解决问题,首先我们先定位问题产生的原因,先确定下是否是硬件的原因导致的compressed data is corrupt。
检查操作系统日志报错信息:
1.在“messages-20191229”中,

2.在数据日志中报错信息如下:


2.解决思路
通过系统日志和数据库日志我们发现崩溃block的大概对象以及具体的位置,还有有可能产生的原因是硬件问题带来的!系统日志反应系统文件block的头部信息报错,同时数据日志又告诉我们不止是corrupt问题,还有伴随着对象page的损坏。
1、定位page的损坏对象:
v5=#select oid,relname from pg_class where relfilenode=19705;
oid | relname
-------+------------------------
19705 | i_onedata_wtid_rectime
(1 行记录)
好消息是索引的无效页:
2、定位compressed data is corrupt范围
由于数据库内部已经有相关对象的大概范围,所以我们只需要缩小范围即可。如果我们不知道对象的范围,怎么确定block corrupt的范围呢
1)通过copy转储的方式确定
COPY (selectctid,* FROM tablename ORDER BY ctid) TO '/path/to/file'
2)通过函数查找
create functionchk(anyelement)
returns bool
language plpgsql as $f$
declare t text;
begin t := $1;
return false;
exception when others then return true;
end;
$f$;
select ctidfrom statisticdata where chk(statisticdata);
2.1.如何解决问题
1、关于索引页的问题:
处理索引无效页的问题就比较简单了!
Reindex index i_onedata_wtid_rectime;
2、关于compressed data is corrupt问题
此种问题目前还未能找到相关的修复的办法在数据库内部,处理的方式同样需要找到出问题的block位置,之后可以转储有效数据到新的对象,至于出现corrupt的记录位置如果有备份可以通过备份来进行数据的恢复。
2.2.计算corrupt的范围并恢复
1、通过select 对象时间范围定义corrupt的位置

2、拷贝$PGDATA数据文件副本
因为涉及到pg_dump转储对象所以需要把有问题的对象清理,永远不要忘记备份的重要性。
3、通过数据库内部完成有效数据的迁移
Create table like 的方式复制表的结构信息。
Insertinto select 的方式排除无效数据的块到新的表下
4、通过备份恢复指定的表
通过新恢复的表提取corrupt无效范围内的数据。
5、删除原表
Drop table对象,通过pg_dump转储对象问题解决
3.实践情况
此文档通过定位compressed data is corrupt 的对象无效数据范围来完成有效数据的迁移,同时通过备份的数据恢复了无效对象的数据集,此方法可以帮助解决底层数据文件block解析问题,通过实际的环境恢复来说此方法可以解决此类问题。
4.效果评价
此方法最小限度的定位到了数据范围,如果没有备份可以把损失降到最低,目前还没找到compressed data is corrupt问题的其他恢复方法,解决问题是一方面,另一方面还是要定位问题,避免此类问题的在此发生。
5.推广建议
建议在不知道corrupt的范围的情况下,copy+select的方式定位具体的范围,相对来说较简单。
6.参考资料
无
――完――
关于我们
中国开源软件推进联盟PostgreSQL分会(简称:PG分会)于2017年成立,由国内多家PG生态企业所共同发起,业务上接受工信部产业发展研究院指导。PG分会致力于构建PG产业生态,推动PG产学研用发展,是国内唯一受官方认可的PG行业协会组织。





