数据恢复咨询热线:400-666-3702  

欢迎访问南京兆柏数据恢复公司,专业数据恢复15年

兆柏数据恢复公司

 行业新闻

 当前位置: 主页 > 行业新闻

PostgreSQL块损坏模拟修复

浏览量: 次 发布日期:2023-09-17 11:49:04

PostgreSQL块损坏模拟修复

  报错信息:ERROR:   invalid page in block 10 of relation "base/13593/11025587"

  测试环境

  1、创建表测试

  2、查看数据路径

  3、 checkpoint

  记得做checkpoint,不然可能dd导出的数据是空的

  4、备份数据文件

  5、查看块数据

  我们查看第10块的数据,总共有185条数据

  6、导出块数据

  将第10个数据块导出:

  7、替换数据

  8、对比

  9、模拟文件损坏

  将替换的数据写入到数据文件中,来模拟数据文件损坏

  需要加入conv=notrunc,保证只替换第10页,不加的话10页后面的数据都丢失了。

  这样表中就有两条一样的数据了,但是还是能查询出来,表也没报错

  神奇的是,该sql能走索引,而且查询出来了。这里检查了zero_damaged_pages=off,并未打开

  11、重建索引报错:

  未能复现出ERROR:  invalid page in block 10 of relation 的报错但是很明显数据确实被破坏了,表中有重复的数据,而且索引重建冲突

  上面还有一点,vacuum full没有报错,而reindex的时候报错了,我们都知道vacuum是会清理掉索引膨胀的,单并没有重建这个索引。上面替换进去的页被正常查出来了,但是数据也是重复的。

  从这篇文章来看要开启checksum才会报页面损坏,如果不开的话,很可能就是上面的情况,只是数据冲突,还是能继续访问。上面的测试基于pg12.3https://blog.csdn.net/weixin_43230594/article/details/123781575

  打开checksum,然后使用dd模拟坏块

  1、查看checksum是否打开,0表示关闭,1表示打开

  2、关闭数据库,打开checksum

  3、开启checksum

  4、模拟数据损坏

  5、使用dd

  打开checksum能够复现出块损坏的报错

  6、使用checksum检查块

  停掉数据库使用checksum检查,可以可能出我开始手动损坏的块都检测出来了,但是查询是正常的

  7、转换

  将checksum报错16进制转换为2进制刚好能对上

  8、打开zero_damaged_pages

  打开checksum后能复现报错,尝试使用zero_damaged_pages来忽略坏块

  可以看到确实可以访问表了,但是警告仍然存在,这给了我们操作空间,能访问意味着我们可以备份这个表

  1、关闭checksum

  2、 启动数据库查询数据,发现数据发生了错误

  3、zero_damaged_pages

  设置后还是有数据冲突的问题,当数据重复且能正常查询出来的时候设置zero_damaged_pages这个参数已经没有效果,因为数据已经正常只是索引里面冲突了,zero_damaged_pages不能解决数据冲突的问题

  小结:也就是说没有开启checksum下的数据文件损坏,可能导致查询到错误的数据

  我们再次复现上面第一个例子,先打开checksum,看能检查出报错,另外就是备份数据文件,看能否从备份的数据文件中还原损坏的块

  1、我们用第一个模拟文件损坏来实验

  打开checksum以后复现:

  也就是说如果一开始打开了checksum,那么检测出损坏的块,即使后面关掉checksum仍然会报错

  2、从读库还原坏块

  使用dd将备份的数据文件替换进去,加入11121060_bak是流复制中读库的数据

  3、重启数据库

  有高可用情况可以非常快速的恢复,且不丢失数据dd抹除

  生产环境谨慎使用,如果没有备份,可以抹除掉损坏的块

  1、dd抹除,conv=notrunc 会阻止 dd 截断表的其余部分。

  如果不加conv=notrunc,将会丢失大量数据

  表示块大小,seek标识第10块,count=1标识总共处理1块,if标识输入的文件,of标识输出的文件

  抹除后执行vacuum

  我们可以看到最开始插入的数据是20000001,刚好相差185条数据,也就是丢失了第10页的数据导出正常数据

  如果害怕dd使用有问题,那么我们可以考虑将正常的数据导出使用sql来处理,导出非坏块的数据

  1、根据报错找到对应的坏块

  将数据分别插入到临时表中

  对整库进行备份,让运维人员对整个磁盘设备进行检查是否有坏块,并修复坏块

  另外看到说可以删除坏块的方式,测试发现不可行

  如上打开checksum示例,我们可以打开这个参数来忽略坏块,然后备份数据,当然某些情况下这个参数也不好使,还得用上面两种方法

  1、在没有打开checksum的情况下块损坏后还是能访问,但是数据错误

  2、如果报错页损坏invalid page in block of relation base ,那么可以设置zero_damaged_pages=on一般就可以访问表,使用dump的方式将数据备份出来。

  3、第2步如果不行那么就需要特殊处理

  常见的方式有使用dd抹除损坏的这个页,另外就是使用临时表的方式将有用的数据导出来,然后还原数据

  4、如果有做高可用,那么可以直接从备库的数据文件中还原损坏的块,此办法较快

  5、checksum可以检查具体有那些块是损坏的,然后针对全库进行修复

  6、做好备份,并且定期检查备份的正确是很有必要的。块损坏会导致备份失败

  zero_damaged_pages:检测到损坏的页头通常会导致PostgreSQL报告错误,中止当前事务。设置为 on 会导致系统报告警告,将内存中损坏的页面清零,然后继续处理。这种行为会破坏数据,即损坏页面上的所有行。但是,它确实允许您克服错误并从表中可能存在的任何未损坏的页面中检索行。如果由于硬件或软件错误而发生损坏,它对于恢复数据很有用。在您放弃从表的损坏页恢复数据的希望之前,您通常不应设置此选项。清零页不会被强制写入磁盘,因此建议在再次关闭此参数之前重新创建表或索引。默认设置为,并且只能由超级用户更改。

 

相关推荐