什么是数据损坏
存储故障通常是指读取或写入数据的存储介质出现的物理上的故障,存储故障通常会带来数据损坏甚至数据丢失的风险。
checksum
PostgreSQL在9.3版本开始,引入了checksum,使用checksum可以检验数据块的损坏
页面有效性检验发生在离开共享缓冲区和进入共享缓冲区之前。
checksum写入
当将页面从缓冲区缓存写入到操作系统页面缓存(OS Cache)时,就会计算checksum值并写入数据页中。
checksum校验
每次读取该块时,checksum值就会重新计算,并与所存储的checksum值进行比较。这可以检验数据是否损坏。
checksum使用示例
1、先检查下当前数据库是否开启checksum,0代表关闭,1代表打开
pg_controldata -D /usr/local/pgsql/data |grep checksum
2、创建表并查询表的物理存储位置
create table tab1(a int primary key ,b text);
insert into tab1 values (1,'hello postgres'); select pg_relation_filepath('tab1');
3、关闭数据库,启用checksum
pg_ctl -D /usr/local/pgsql/data stop
pg_checksums -D /usr/local/pgsql/data --enable --progress
pg_ctl -D /usr/local/pgsql/data start
4、使用dd命令模拟数据文件损坏
dd bs=8192 count=1 seek=1 of=/usr/local/pgsql/data/base/12723/16384 if=/usr/local/pgsql/data/base/12723/16384
5、此时再去查询表,可以看到查询报错:
select * from tab1 ;
6、停掉数据库,使用checksum检查数据页的错误
7、将16进制的D7B1转换为10进制,得到55,217,这和错误是匹配的。
8、没有开启checksum下的数据文件损坏,可能导致查询到错误的数据
现在关掉checksum
pg_ctl -D /usr/local/pgsql/data stop
pg_checksums -D /usr/local/pgsql/data --disable --progress
9、启动数据库后去查询数据,可以发现查询出的数据是错误的
数据页损坏如何处理
可以通过设置zero_damaged_pages参数去清理损坏的页面,然后获取剩下的结果。
show zero_damaged_pages;
set zero_damaged_pages=on;
select * from tab1 ;
我们看一下这个参数的含义:
zero_damaged_pages
( boolean
)
检测到损坏的页头通常会导致PostgreSQL报告错误,中止当前事务。设置zero_damaged_pages
为 on 会导致系统报告警告,将内存中损坏的页面清零,然后继续处理。这种行为会破坏数据,即损坏页面上的所有行。但是,它确实允许您克服错误并从表中可能存在的任何未损坏的页面中检索行。如果由于硬件或软件错误而发生损坏,它对于恢复数据很有用。在您放弃从表的损坏页恢复数据的希望之前,您通常不应设置此选项。清零页不会被强制写入磁盘,因此建议在再次关闭此参数之前重新创建表或索引。默认设置为off
,并且只能由超级用户更改。
以上,说明这参数的使用需要谨慎。
开启checksum带来的影响
On an average if you enable checksum the performance cost would be more than 2% and for inserts, the average difference was 6%. For selects, that jumps to 19%.
平均而言,如果启用校验和,性能成本将超过 2%,对于insert,平均差异为 6%。对于select,这会跳到 19%。
完整的性能影响计算准则可以参见:https://www.endpoint.com/blog/2015/12/postgres-checksum-performance-impact/
参考文档:https://postgreshelp.com/postgresql-checksum/