5

postgresql 15源码浅析(5)—— pg-m6米乐安卓版下载

postgresql的控制文件保存initdb期间初始化的信息、wal信息、检查点信息等。文件位于$pgdata/global/pg_control。postgresql集簇存在期间(运行或停止),一些工具或进程可以查看或修改该文件。本文整理了(几乎)所有修改和查看pg_control控制文件的地方,结合源码进行了梳理,希望能对pg的控制文件有跟进一步的了解。

先上图,共有5个服务端工具、4个内置函数和1个后端进程可以对pg_control控制文件进行查询或修改操作,后文将进行介绍。

image.png

pg_control文件是一个大小8192字节的二进制文件,文件内容是将结构体controlfiledata以二进制的形式写入pg_control文件中。

  • pg_control文件大小
#define pg_control_file_size 8192
  • controlfiledata数据结构

源码位于src/include/catalog/pg_control.h

/* * contents of pg_control. */ typedef struct controlfiledata { uint64 system_identifier; uint32 pg_control_version; /* pg_control_version */ uint32 catalog_version_no; /* see catversion.h */ dbstate state; /* see enum above */ pg_time_t time; /* time stamp of last pg_control update */ xlogrecptr checkpoint; /* last check point record ptr */ checkpoint checkpointcopy; /* copy of last check point record */ xlogrecptr unloggedlsn; /* current fake lsn value, for unlogged rels */ xlogrecptr minrecoverypoint; timelineid minrecoverypointtli; xlogrecptr backupstartpoint; xlogrecptr backupendpoint; bool backupendrequired; int wal_level; bool wal_log_hints; int maxconnections; int max_worker_processes; int max_wal_senders; int max_prepared_xacts; int max_locks_per_xact; bool track_commit_timestamp; uint32 maxalign; /* alignment requirement for tuples */ double floatformat; /* constant 1234567.0 */ #define floatformat_value 1234567.0 uint32 blcksz; /* data block size for this db */ uint32 relseg_size; /* blocks per segment of large relation */ uint32 xlog_blcksz; /* block size within wal files */ uint32 xlog_seg_size; /* size of each wal segment */ uint32 namedatalen; /* catalog name field width */ uint32 indexmaxkeys; /* max number of columns in an index */ uint32 toast_max_chunk_size; /* chunk size in toast tables */ uint32 loblksize; /* chunk size in pg_largeobject */ bool float8byval; /* float8, int8, etc pass-by-value? */ uint32 data_checksum_version; char mock_authentication_nonce[mock_auth_nonce_len]; pg_crc32c crc; } controlfiledata;
  • get_controlfile

get_controlfile主要功能是将二进制文件pg_control读取到controlfiledata中。

// 函数定义 controlfiledata *get_controlfile(const char *datadir, bool *crc_ok_p);
// 关键代码,读取控制文件到结构体中 r = read(fd, controlfile, sizeof(controlfiledata));
  • update_controlfile

update_controlfile主要功能室将结构体controlfiledata中的内容以二进制的形式写入pg_control中。

// 函数定义 void update_controlfile(const char *datadir, controlfiledata *controlfile, bool do_sync)
// 二进制形式打开文件 if ((fd = open(controlfilepath, o_wronly | pg_binary, pg_file_create_mode)) == -1) // 写入内容 if (write(fd, buffer, pg_control_file_size) != pg_control_file_size)
  • read_controlfile

在pg_resetwal中单独实现了一个read_controlfile函数,这里处理读取pg_control控制文件,主要的功能是检查控制文件的长度、版本号、wal文件的大小。个人觉得,其实这里用read_controlfile这个名字未必合理。

static bool read_controlfile(void) { …… if ((fd = open(xlog_control_file, o_rdonly | pg_binary, 0)) < 0) { …… } …… len = read(fd, buffer, pg_control_file_size); …… if (len >= sizeof(controlfiledata) && ((controlfiledata *) buffer)->pg_control_version == pg_control_version) { …… if (!eq_crc32c(crc, ((controlfiledata *) buffer)->crc)) { …… } …… if (!isvalidwalsegsize(controlfile.xlog_seg_size)) { …… } return true; } …… }

服务端工具pg_controldata

这个工具实现十分简单,就是读取pg_control然后进行打印输出。

image.png

内部函数

postgresql 提供了4个内置函数对控制文件中的信息进行了分类显示。

pg_control_init(初始化集簇initdb的参数)

image.png

pg_control_system(系统参数)

image.png

pg_control_checkpoint(checkpoint参数)

image.png

pg_control_recovery(recovery参数)

image.png

服务端工具pg_checksums

pg_checksums在postgresql集簇中检查、启用或禁用数据校验和。运行pg_checksums之前,必须彻底关闭服务器。验证校验和时,如果没有校验和错误,则退出状态为零,如果检测到至少一个校验和失败,则退出状态为非零。启用或禁用校验和时,如果操作失败,则退出状态为非零。

验证校验和时,集簇中的每个文件都要被扫描。启用校验和时,集簇中的每个文件都会被重写。禁用校验和时,仅更新pg_control文件。

服务端工具pg_ctl

pg_clt在备点进行promote时,需要判断备点状态,即备点状态需为db_in_archive_recovery。

static dbstate get_control_dbstate(void) { dbstate ret; bool crc_ok; controlfiledata *control_file_data = get_controlfile(pg_data, &crc_ok); if (!crc_ok) { write_stderr(_("%s: control file appears to be corrupt\n"), progname); exit(1); } ret = control_file_data->state; pfree(control_file_data); return ret; }

dbstate的几种状态如下:

/* * system status indicator. note this is stored in pg_control; if you change * it, you must bump pg_control_version */ typedef enum dbstate { db_startup = 0, db_shutdowned, db_shutdowned_in_recovery, db_shutdowning, db_in_crash_recovery, db_in_archive_recovery, db_in_production } dbstate;

服务端工具pg_resetwal

通过函数read_controlfile,实现了读取pg_control,目的是为了后续对pg_control的修改。

服务端工具pg_rewind

通过函数read_controlfile,实现了读取pg_control,目的是为了后续对pg_control的修改。

服务端工具pg_checksums

之前提到pg_checksums会读取pg_control控制文件,同时pg_checksums也会更新pg_control控制文件,主要是更新data page checksum version的值。

image.png

当执行pg_checksums -e时,开启校验,会将控制文件中data page checksum version更新为1,如果是 -d 关闭校验,则data page checksum version被更新为0.

/* * finally make the data durable on disk if enabling or disabling * checksums. flush first the data directory for safety, and then update * the control file to keep the switch consistent. */ if (mode == pg_mode_enable || mode == pg_mode_disable) { controlfile->data_checksum_version = (mode == pg_mode_enable) ? pg_data_checksum_version : 0; if (do_sync) { pg_log_info("syncing data directory"); fsync_pgdata(datadir, pg_version_num); } pg_log_info("updating control file"); update_controlfile(datadir, controlfile, do_sync); if (verbose) printf(_("data checksum version: %u\n"), controlfile->data_checksum_version); if (mode == pg_mode_enable) printf(_("checksums enabled in cluster\n")); else printf(_("checksums disabled in cluster\n")); }

服务端工具pg_resetwal

pg_resetwal可以重置损坏的wal日志或根据事务号进行重置wal日志文件,同时如有必要同时更新pg_control文件。

/* * write out the new pg_control file. */ static void rewritecontrolfile(void) { /* * adjust fields as needed to force an empty xlog starting at * newxlogsegno. */ xlogsegnooffsettorecptr(newxlogsegno, sizeofxloglongphd, walsegsz, controlfile.checkpointcopy.redo); controlfile.checkpointcopy.time = (pg_time_t) time(null); controlfile.state = db_shutdowned; controlfile.checkpoint = controlfile.checkpointcopy.redo; controlfile.minrecoverypoint = 0; controlfile.minrecoverypointtli = 0; controlfile.backupstartpoint = 0; controlfile.backupendpoint = 0; controlfile.backupendrequired = false; /* * force the defaults for max_* settings. the values don't really matter * as long as wal_level='minimal'; the postmaster will reset these fields * anyway at startup. */ controlfile.wal_level = wal_level_minimal; controlfile.wal_log_hints = false; controlfile.track_commit_timestamp = false; controlfile.maxconnections = 100; controlfile.max_wal_senders = 10; controlfile.max_worker_processes = 8; controlfile.max_prepared_xacts = 0; controlfile.max_locks_per_xact = 64; /* the control file gets flushed here. */ update_controlfile(".", &controlfile, true); }

服务端工具pg_rewind

将postgresql数据目录同步到新的时间线。

static controlfiledata controlfile_target; static controlfiledata controlfile_source; static controlfiledata controlfile_source_after;

从源控制文件中读取必要信息,并重新写入目标控制文件。

pg_control保存了4类信息,分别是postgres集簇的初始化信息、系统信息、checkpoint信息、recovery信息。多种服务端工具会对pg_control进行查看或者修改。本文从代码的角度梳理了对pg_control读写相关的代码,希望能对大家了解postgres控制文件有所帮助。

最后修改时间:2022-07-30 23:55:25
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【米乐app官网下载的版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论

网站地图