背景
使用PostgreSQL pitr,数据库恢复到一个时间点后,这个数据库的所有BLOCK是否都是一致的?
数据库在DOWN机恢复后,数据文件所有BLOCK是否一致?
定期抽查数据库的数据文件是否BLOCK级一致?
以上需求如何快速的满足呢?
PostgreSQL允许用户开启block checksum功能,使用pg_verify_checksums工具,可以对整个数据库或指定的数据文件进行checksum校验,确保数据文件逻辑上一致。
pg_verify_checksums 校验数据块一致性
1、停库,目前不支持OPEN状态下的校验。
2、使用pg_verify_checksums校验
pg_verify_checksums verifies data checksums in a PostgreSQL database cluster.
Usage:
pg_verify_checksums [OPTION]... [DATADIR]
Options:
[-D, --pgdata=]DATADIR data directory
-v, --verbose output verbose messages
-r RELFILENODE check only relation with specified relfilenode
-V, --version output version information, then exit
-?, --help show this help, then exit
If no data directory (DATADIR) is specified, the environment variable PGDATA
is used.
Report bugs to <pgsql-bugs@postgresql.org>.
pg_verify_checksums -D /data01/digoal/pg_root8009
Checksum scan completed
Data checksum version: 1
Files scanned: 932
Blocks scanned: 2909
Bad checksums: 0
3、目前pg_verify_checksums识别到错误会直接退出程序
pg_verify_checksums -D /data01/digoal/pg_root8009
pg_verify_checksums: could not read block 0 in file "/data01/digoal/pg_root8009/base/13285/13120_fsm": read 1023 of 8192
static void
scan_file(const char *fn, BlockNumber segmentno)
{
PGAlignedBlock buf;
PageHeader header = (PageHeader) buf.data;
int f;
BlockNumber blockno;
f = open(fn, O_RDONLY | PG_BINARY);
if (f < 0)
{
fprintf(stderr, _("%s: could not open file \"%s\": %s\n"),
progname, fn, strerror(errno));
exit(1);
}
files++;
for (blockno = 0;; blockno++)
{
uint16 csum;
int r = read(f, buf.data, BLCKSZ);
if (r == 0)
break;
if (r != BLCKSZ)
{
fprintf(stderr, _("%s: could not read block %u in file \"%s\": read %d of %d\n"),
progname, blockno, fn, r, BLCKSZ);
exit(1);
}
blocks++;
/* New pages have no checksum yet */
if (PageIsNew(header))
continue;
csum = pg_checksum_page(buf.data, blockno + segmentno * RELSEG_SIZE);
if (csum != header->pd_checksum)
{
if (ControlFile->data_checksum_version == PG_DATA_CHECKSUM_VERSION)
fprintf(stderr, _("%s: checksum verification failed in file \"%s\", block %u: calculated checksum %X but block contains %X\n"),
progname, fn, blockno, csum, header->pd_checksum);
badblocks++;
}
}
if (verbose)
fprintf(stderr,
_("%s: checksums verified in file \"%s\"\n"), progname, fn);
close(f);
}
如果期望扫描完所有文件,并将所有有错误的文件打印出来,需要修改一下pg_verify_checksums的代码
注意
版本要求,PostgreSQL 11以上。
低于11的版本,需要将pg_verify_checksums的功能向下PORT一下。
参考
https://www.postgresql.org/docs/11/pgverifychecksums.html
PostgreSQL 许愿链接
您的愿望将传达给PG kernel hacker、数据库厂商等, 帮助提高数据库产品质量和功能, 说不定下一个PG版本就有您提出的功能点. 针对非常好的提议,奖励限量版PG文化衫、纪念品、贴纸、PG热门书籍等,奖品丰富,快来许愿。开不开森.