学习目的
使用pg_checksums
功能检查数据完整性,确保没有损坏。这一检查可以定期进行,以防止潜在的数据丢失和损坏。但是这玩意目前我知道的有几个前提条件,一是关于关闭数据库,二是启用Data page checksum version这个参数(pg_controldata的这个参数下输出Data page checksum version: 1),才可以
开户
root@BJ-015908:/usr/local/pgsqldebug/bin# ./pg_checksums -D usr/local/pgsqldebug/data/ -e
Checksum operation completed
Files scanned: 1237
Blocks scanned: 4124
pg_checksums: syncing data directory
pg_checksums: updating control file
Checksums enabled in cluster复制
/usr/local/pgBuild/bin/pg_controldata -D usr/local/pgdh/data
Data page checksum version: 1复制
关闭
postgres@BJ-015908:~$ /usr/local/pgBuild/bin/pg_checksums -D /usr/local/pgdh/data -d
pg_checksums: syncing data directory
pg_checksums: updating control file
Checksums disabled in cluster
postgres@BJ-015908:~$复制
/usr/local/pgBuild/bin/pg_controldata -D /usr/local/pgdh/data
Data page checksum version: 0复制
实践
前提条件
必须关闭集群
postgres@BJ-015908:~$ /usr/local/pgBuild/bin/pg_checksums -D /usr/local/pgdh/data
pg_checksums: error: cluster must be shut down
postgres@BJ-015908:~$复制
必须 Data page checksum version的参数为1,启动状态
root@BJ-015908:/usr/local/pgsqldebug/bin# ./pg_checksums -D /usr/local/pgsqldebug/data/
pg_checksums: error: data checksums are not enabled in cluster
root@BJ-015908:/usr/local/pgsqldebug/bin#复制
函数调用
请出我们今天的主角GDB工具入场
postgres@BJ-015908:~$ gdb --args /usr/local/pgBuild/bin/pg_checksums -D /usr/local/pgdh/data
复制
打入断点调试
b 451
复制
如图

传入数据目录并分配变量
case 'D':
DataDir = optarg;
break;复制
数据目录设置
if (DataDir == NULL)
{
if (optind < argc)
DataDir = argv[optind++];
else
DataDir = getenv("PGDATA");复制
读取%s/global/pg_control
文件
ControlFile = get_controlfile(DataDir, &crc_ok);
复制
限制条件,CRC校验,版本校验,block size校验,数据库状态为DB_SHUTDOWNED模式或者DB_SHUTDOWNED_IN_RECOVERY模式,等等情况
/* Read the control file and check compatibility */
ControlFile = get_controlfile(DataDir, &crc_ok);
if (!crc_ok)
{
pg_log_error("pg_control CRC value is incorrect");
exit(1);
}
if (ControlFile->pg_control_version != PG_CONTROL_VERSION)
{
pg_log_error("cluster is not compatible with this version of pg_checksums");
exit(1);
}
if (ControlFile->blcksz != BLCKSZ)
{
pg_log_error("database cluster is not compatible");
fprintf(stderr, _("The database cluster was initialized with block size %u, but pg_checksums was compiled with block size %u.\n"),
ControlFile->blcksz, BLCKSZ);
exit(1);
}
/*
* Check if cluster is running. A clean shutdown is required to avoid
* random checksum failures caused by torn pages. Note that this doesn't
* guard against someone starting the cluster concurrently.
*/
if (ControlFile->state != DB_SHUTDOWNED &&
ControlFile->state != DB_SHUTDOWNED_IN_RECOVERY)
{
pg_log_error("cluster must be shut down");
exit(1);
}
if (ControlFile->data_checksum_version == 0 &&
mode == PG_MODE_CHECK)
{
pg_log_error("data checksums are not enabled in cluster");
exit(1);
}
if (ControlFile->data_checksum_version == 0 &&
mode == PG_MODE_DISABLE)
{
pg_log_error("data checksums are already disabled in cluster");
exit(1);
}
if (ControlFile->data_checksum_version > 0 &&
mode == PG_MODE_ENABLE)
{
pg_log_error("data checksums are already enabled in cluster");
exit(1);
}复制
打工人登场,其中files与blocks在其它函数中有调用,算出来的
/* Operate on all files if checking or enabling checksums */
if (mode == PG_MODE_CHECK || mode == PG_MODE_ENABLE)
{
/*
* If progress status information is requested, we need to scan the
* directory tree twice: once to know how much total data needs to be
* processed and once to do the real work.
*/
if (showprogress)
{
total_size = scan_directory(DataDir, "global", true);
total_size += scan_directory(DataDir, "base", true);
total_size += scan_directory(DataDir, "pg_tblspc", true);
}
(void) scan_directory(DataDir, "global", false);
(void) scan_directory(DataDir, "base", false);
(void) scan_directory(DataDir, "pg_tblspc", false);
if (showprogress)
progress_report(true);
printf(_("Checksum operation completed\n"));
printf(_("Files scanned: %s\n"), psprintf(INT64_FORMAT, files));
printf(_("Blocks scanned: %s\n"), psprintf(INT64_FORMAT, blocks));
if (mode == PG_MODE_CHECK)
{
printf(_("Bad checksums: %s\n"), psprintf(INT64_FORMAT, badblocks));
printf(_("Data checksum version: %u\n"), ControlFile->data_checksum_version);
if (badblocks > 0)
exit(1);
}
}复制
files与blocks是在scan_file部分函数代码
static void
scan_file(const char *fn, BlockNumber segmentno)
{
PGAlignedBlock buf;
PageHeader header = (PageHeader) buf.data;
int f;
BlockNumber blockno;
int flags;
Assert(mode == PG_MODE_ENABLE ||
mode == PG_MODE_CHECK);
flags = (mode == PG_MODE_ENABLE) ? O_RDWR : O_RDONLY;
f = open(fn, PG_BINARY | flags, 0);
if (f < 0)
{
pg_log_error("could not open file \"%s\": %m", fn);
exit(1);
}
files++;
for (blockno = 0;; blockno++)
{
uint16 csum;
int r = read(f, buf.data, BLCKSZ);
if (r == 0)
break;
if (r != BLCKSZ)
{
if (r < 0)
pg_log_error("could not read block %u in file \"%s\": %m",
blockno, fn);
else
pg_log_error("could not read block %u in file \"%s\": read %d of %d",
blockno, fn, r, BLCKSZ);
exit(1);
}
blocks++;复制
总结
我其实就是想知道它是怎么来的,贴近原理部分,这样的理解力能增加,不要只知道结果,不要过程,其它没了,just for fun
文章转载自SmallDB,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。
评论
相关阅读
PostgreSQL初/中/高级认证考试(3.15)通过考生公示
开源软件联盟PostgreSQL分会
402次阅读
2025-03-20 09:50:36
9.9 分高危漏洞,尽快升级到 pgAdmin 4 v9.2 进行修复
严少安
312次阅读
2025-04-11 10:43:23
3月“墨力原创作者计划”获奖名单公布
墨天轮编辑部
307次阅读
2025-04-15 14:48:05
openHalo问世,全球首款基于PostgreSQL兼容MySQL协议的国产开源数据库
严少安
248次阅读
2025-04-07 12:14:29
IvorySQL 4.4 发布 - 基于 PostgreSQL 17.4,增强平台支持
通讯员
237次阅读
2025-03-20 15:31:04
PG vs MySQL 执行计划解读的异同点
进击的CJR
172次阅读
2025-03-21 10:50:08
postgresql+patroni+etcd高可用安装
necessary
135次阅读
2025-03-28 10:11:23
手把手教你在 openKylin 上部署 IvorySQL 4.4
严少安
131次阅读
2025-03-27 20:41:28
从 Oracle 到 PostgreSQL迁移成本评估揭秘
梧桐
127次阅读
2025-03-27 17:21:42
转发有奖 | PostgreSQL 16 PGCM高级认证课程直播班招生中!
墨天轮小教习
122次阅读
2025-04-14 15:58:34