什么是控制文件
控制文件是一个 8kb 大小的二进制文件,该文件默认位置位于$PGDATA/global/pg_control ,该文件中记录了 postgreSQL 服务器内部状态的各方面信息。内容可以分为两部分,一种是静态数据(不会变动),如 initdb 初始化的一些参数,另一种是动态数据,它会随着数据库运行的时间而变动,如我们后面会说到的检查点和postgres.conf相关参数。
数据库会启动前会先打开这个文件两次,第一次是检测该文件是否存在,第二次是为了校验内容。
该文件非常非常非常重要,如果该文件不存在或者损坏(数据内容和当前启动服务的postmaster服务版本不匹配),论出现以上两种情形中的任何一种,PostgreSQL服务都不会正常启动。因为这两种情形的出现都明显表明当前环境上的PostgreSQL服务出现了未知的问题,是不正常的现象
该文件虽然大小为 8kb,但实际有效字段值内容仅有几百字节,剩下的数据全用零填充,这样做减少了在读取pg_control文件时候发生过早的EOF错误的几率。
控制文件解析
想要查看控制文件内容,可通过安装目录 bin 路径下的pg_controldata 工具。
pg_controldata -D /data/pgsql/data/
下面输出的内容为 17.1 版本
pg_control version number: 1700
Catalog version number: 202406281
Database system identifier: 7502811852738500652
Database cluster state: in production
pg_control last modified: Sat May 24 23:31:41 2025
Latest checkpoint location: 1/750000B8
Latest checkpoint's REDO location: 1/75000060
Latest checkpoint's REDO WAL file: 000000010000000100000075
Latest checkpoint's TimeLineID: 1
Latest checkpoint's PrevTimeLineID: 1
Latest checkpoint's full_page_writes: on
Latest checkpoint's NextXID: 0:889
Latest checkpoint's NextOID: 41118
Latest checkpoint's NextMultiXactId: 1
Latest checkpoint's NextMultiOffset: 0
Latest checkpoint's oldestXID: 730
Latest checkpoint's oldestXID's DB: 1
Latest checkpoint's oldestActiveXID: 889
Latest checkpoint's oldestMultiXid: 1
Latest checkpoint's oldestMulti's DB: 1
Latest checkpoint's oldestCommitTsXid:0
Latest checkpoint's newestCommitTsXid:0
Time of latest checkpoint: Sat May 24 23:31:38 2025
Fake LSN counter for unlogged rels: 0/3E8
Minimum recovery ending location: 0/0
Min recovery ending loc's timeline: 0
Backup start location: 0/0
Backup end location: 0/0
End-of-backup record required: no
wal_level setting: replica
wal_log_hints setting: off
max_connections setting: 100
max_worker_processes setting: 8
max_wal_senders setting: 10
max_prepared_xacts setting: 0
max_locks_per_xact setting: 64
track_commit_timestamp setting: off
Maximum data alignment: 8
Database block size: 8192
Blocks per segment of large relation: 131072
WAL block size: 8192
Bytes per WAL segment: 16777216
Maximum length of identifiers: 64
Maximum columns in an index: 32
Maximum size of a TOAST chunk: 1996
Size of a large-object chunk: 2048
Date/time type storage: 64-bit integers
Float8 argument passing: by value
Data page checksum version: 0
Mock authentication nonce: bbf2a8aa358d0a829ccf49d6e252e5a79cbd9be4eccba675120fbf456cfb85ec
输出内容相信大部分初学者看不懂,没事,慢慢学就行了。我们这里挑出几个重要的参数说说就行了。
● Database cluster state 记录实例的状态,该参数有以下这些值
a. starting up:表示数据库正在启动状态。
b. shut down: 数据库实例(非Standby)正常关闭后控制文件中就是此状态。
c. shut down in recovery:Standby实例正常关闭后控制文件中就是此状态。
d. shutting down:正常停库时,先做checkpoint,开始做checkpoint时,会把状态设置为此状态,做完后把状态设置为shut down。
e. in crash recovery:数据库实例非异常停止后,重新启动后,会先进行实例的恢复,在实例恢复时的状态就是此状态。
f. in archive recovery:Standby实例正常启动后,就是此状态。
g. in production:数据库实例正常启动后就是此状态。Standby数据库正常启动后不是此状态
● Latest checkpoint location:最后一次检查点
● Latest checkpoint's REDO location:记录数据库日志文件上检查点,数据库异常关闭后会从这个点开始恢复。有人就有疑问了为什么有checkpoint还要有redo,这里我们卖个关子,等后面讲检查点再细说。
● Latest checkpoint's REDO WAL file:当前wal日志。
● Database block size:数据块大小
● Maximum length of identifiers:目录名称字段宽度,是指一些数据库对象名称的最大长度,如表名、索引名的最大长度,目前是64
● Maximum columns in an index:表示一个索引最多多少列
● Maximum size of a TOAST chunk:TOAST 表中的块大小,是TOAST chunk的最大长度。TOAST是解决当列的内容太长,在一个数据块中存不下时的一种行外存储的方式
● Latest checkpoint's NextXID前面是新纪元值,冒号后面是下一个事务号,当前事务号最大值安全值可以在pg_xact目录下通过文件名计算出来。
● Latest checkpoint's NextMultiXactId参数,可以通过pg_multixact/offsets文件名计算出来安全值。
● Latest checkpoint's NextMultiOffset参数,当恢复控制文件时可以通过pg_multixact/members文件夹下计算出此参数的安全值。
PostgreSQL控制文件维护
固定部分:初始化数据库时产生,固定不变
有些信息随时更新:如果发生检查点、备份、日志切换等操作,则自动更新
postgres.conf相关参数被更新:如果配置文件中重要的相关参数被修改,则也会自动更新
数据库备份时会一起备份
不能手动修改该文件
启动和恢复数据库时需要,当前没有避免发生单一故障点而设计的保护策略
如何重做控制文件
如果在无备份的情况下误删了控制文件,那么怎么重做该控制文件。Pg10版本以前版本使用pg_resetxlog工具
Pg10及以后版本使用pg_resetwal工具。
$ pg_resetwal --help
pg_resetwal resets the PostgreSQL write-ahead log.
Usage:
pg_resetwal [OPTION]... DATADIR
Options:
[-D, --pgdata=]DATADIR data directory
-f, --force force update to be done even after unclean shutdown or
if pg_control values had to be guessed
-n, --dry-run no update, just show what would be done
-V, --version output version information, then exit
-?, --help show this help, then exit
Options to override control file values:
-c, --commit-timestamp-ids=XID,XID
set oldest and newest transactions bearing
commit timestamp (zero means no change)
-e, --epoch=XIDEPOCH set next transaction ID epoch
-l, --next-wal-file=WALFILE set minimum starting location for new WAL
-m, --multixact-ids=MXID,MXID set next and oldest multitransaction ID
-o, --next-oid=OID set next OID
-O, --multixact-offset=OFFSET set next multitransaction offset
-u, --oldest-transaction-id=XID set oldest transaction ID
-x, --next-transaction-id=XID set next transaction ID
--wal-segsize=SIZE size of WAL segments, in megabytes
pg_resetwal需要知道四个参数才可以进行重建
-l, --next-wal-file=WALFILE set minimum starting location for new WAL
参数通过指定下一个WAL段文件的名称,手动设置WAL启动位置。下一个段的名字应该大于当前存在pg_wal目录下的任何WAL段文件名。
要注意的是 wal 日志命名是 16 进制,比如说当前文件为 xxxxxx09,那么下一个文件就是xxxxxx0A,而不是xxxxxx10,要注意这一点。
-m, --multixact-ids=MXID,MXID set next and oldest multitransaction ID
手工设置下一个多事物ID和最老的多事务ID。确定下一个多事务 ID(第一部分)的安全值的方法:在数据目录下的pg_multixact/offsets目录中查找最大的数字文件名,然后在它的基础上加一后面跟上 4 个 0
[postgres@192 offsets]$ ls -l
total 8
-rw-------. 1 postgres postgres 8192 May 22 10:41 0000
-m = 0x00010000
-O, --multixact-offset=OFFSET set next multitransaction offset
手工设置下一个多事务偏移量。
确定安全值的方法:查找数据目录下pg_multixact/members目录中最大的数字文件名,然后在它的基础上加一并且乘以 65536,转换成16进制为100000,然后后面加上 4 个 0。
[postgres@192 members]$ ls -l
total 8
-rw-------. 1 postgres postgres 8192 May 10 21:41 0000
[postgres@192 members]$
-O = 0x1000000000
-x, --next-transaction-id=XID set next transaction ID手工设置下一个事务 ID。
确定安全值的方法:在数据目录下的pg_xact目录中查找最大的数字文件名,然后在它的基础上加一后面加 上 5 个 0。
[postgres@192 pg_xact]$ ll -l|head -n 5
total 8
-rw-------. 1 postgres postgres 8192 May 24 15:56 0000
-x=0x000100000
参考文档来源
评论