[PGSQL]PostgreSQL的控制文件内幕分析

引用自:
https://mp.weixin.qq.com/s/kL9ZvbzoylAW55NJu-8RPA

2018-04-24 osdba@乘数科技 乘数科技
控制文件的作用

PostgreSQL的控制文件与Oracle类似,都是记录数据库的一些重要信息。

使用pg_controldata命令就可以显示出控制文件中的内容:

[postgres@pg01 ~]$ pg_controldata
pg_control version number: 942
Catalog version number: 201409291
Database system identifier: 6197591927813975882
Database cluster state: in production
pg_control last modified: Wed 23 Sep 2015 04:14:47 PM CST
Latest checkpoint location: 0/1748510
Prior checkpoint location: 0/1739E70
Latest checkpoint’s REDO location: 0/17484D8
Latest checkpoint’s REDO WAL file: 000000010000000000000001
Latest checkpoint’s TimeLineID: 1
Latest checkpoint’s PrevTimeLineID: 1
Latest checkpoint’s full_page_writes: on
Latest checkpoint’s NextXID: 0/1830
Latest checkpoint’s NextOID: 24582
Latest checkpoint’s NextMultiXactId: 1
Latest checkpoint’s NextMultiOffset: 0
Latest checkpoint’s oldestXID: 1800
Latest checkpoint’s oldestXID’s DB: 1
Latest checkpoint’s oldestActiveXID: 1830
Latest checkpoint’s oldestMultiXid: 1
Latest checkpoint’s oldestMulti’s DB: 1
Time of latest checkpoint: Wed 23 Sep 2015 04:14:46 PM CST
Fake LSN counter for unlogged rels: 0/1
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
Current wal_level setting: hot_standby
Current wal_log_hints setting: off
Current max_connections setting: 100
Current max_worker_processes setting: 8
Current max_prepared_xacts setting: 0
Current max_locks_per_xact setting: 64
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
Float4 argument passing: by value
Float8 argument passing: by value
Data page checksum version: 0
我们下面对上面输出的这些内容进行详细的解析。

我们先讲一些与版本、平台迁移升级有关的一些信息。如果这些信息不同,即使在同一种Linux平台上,数据库也是不能迁移或升级的。在数据库启动过程中,读取控制文件后发现不能兼容则报“database files are incompatible with server”
的错误。

pg_control version number: 控制文件的版本
Catalog version number: 系统表的版本号,PostgreSQL9.4的版本为201409291。PostgreSQL的版本是由三个数字表示“X.Y.Z”,通常是有功能重大变化“X”才会发生变化,而第二个数字“Y”发生变化,通常指系统表发生了变化。最后一位数字的变化,系统表不会发生变化。所以如果只是最后一位数字变化,如把数据库从9.4.3升级到9.4.4,通常只需要把二制程序升级一个就可以了,因为系统表没有变化,数据文件就是能兼容的。
Maximum data alignment: 数据结构最大的对齐值
Database block size: 数据块的大小
Blocks per segment of large relation: 在一些文件系统上,单个文件的大小是受限制的,为此PG会把一个表的数据分到多个数据文件中存储,此值指定了每个数据文件最多多少个数据块。默认为131072个块,每个块8k,则数据文件最大为1G。
WAL block size: WAL日志块的大小
Bytes per WAL segment: WAL日志文件的大小
Maximum length of identifiers: “name”类型的长度,实际指一些数据库对象名称的最大长度,如表名、索引名的最大长度。
Maximum columns in an index: 一个索引最多多少个列。目前是32个。
Maximum size of a TOAST chunk: TOAST chunk的长度。TOAST是解决当列的内容太长,在一个数据块中存不下时的一种行外存储的方式,具体可以见:http://www.postgresql.org/docs/9.4/interactive/storage-toast.html
Size of a large-object chunk: 大对象的chunk的大小
Date/time type storage: Date/time类型是用浮点数(double)类型表示还是由64bit的长整数表示。这与不同的类UNIX平台有关。
Float4 argument passing: Float4类型的参数是传值还是传引用。
Float8 argument passing: Float8类型的参数是传值还是传引用。
Data page checksum version: 数据块checksum的版本,如果是0,则数据块没有使用checksum。只有运行initdb命令时加了-k参数,PostgreSQL才会在数据块上启用checksum功能。
控制文件中还记录了数据库的唯一标识串(Database system identifier):

Database system identifier: 6197591927813975882
这个标识串是一个64bit的整数,其中包含了创建数据库时的时间戳及initdb时初使化的进程号,所以通常是不会重复的。计算方法可以见xlog.c中:

gettimeofday(&tv, NULL);
sysidentifier = ((uint64) tv.tv_sec) << 32;
sysidentifier |= ((uint64) tv.tv_usec) << 12;
sysidentifier |= getpid() & 0xFFF;

如上面的显示的数据库标识串为“6197591927813975882”,通过下面的SQL,我们就可以知道此数据库是什么时候建的:

postgres=# SELECT to_timestamp(((6197591927813975882>>32) & (2^32 -1)::bigint));

to_timestamp

2015-09-23 14:21:57+08
(1 row)
在控制文件中还记录了实例的状态,在命令pg_controldata中的“Database cluster state”项显示的就是控制文件中实例的状态,有以下几种状态:

starting up: 表示数据库正在启动的状态,实际上目前没有使用此状态。
shut down: 数据库实例(非Standby)正常关闭后控制文件中就是此状态。
shut down in recovery: Standby实例正常关闭后控制文件中就是此状态。
shutting down: 当正常停库时,会先做checkpoint,在开始做checkpoint时,会把状态设置为此状态,当做完后会把状态置为shut down。
in crash recovery: 当数据库实例非异常停止后,重新启动后,会先进行实例的恢复,在实例恢复时的状态就是此状态。
in archive recovery: Standby实例正常启动后,就是此状态。
in production: 数据库实例正常启动的后就是此状态。Standby数据库正常启动后不是此状态,而是“in archive recovery”
在源码实现中,实例的状态是用一个枚举类型来表示的,具体见pg_control.h中

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;
下面我们来看一些与PostgreSQL的异常重启后的实例恢复、物理备份的信息:

Latest checkpoint location: 0/1748510
Prior checkpoint location: 0/1739E70
Latest checkpoint’s REDO location: 0/17484D8
Latest checkpoint’s REDO WAL file: 000000010000000000000001
Latest checkpoint’s TimeLineID: 1
Latest checkpoint’s PrevTimeLineID: 1
Latest checkpoint’s full_page_writes: on
Latest checkpoint’s NextXID: 0/1830
Latest checkpoint’s NextOID: 24582
Latest checkpoint’s NextMultiXactId: 1
Latest checkpoint’s NextMultiOffset: 0
Latest checkpoint’s oldestXID: 1800
Latest checkpoint’s oldestXID’s DB: 1
Latest checkpoint’s oldestActiveXID: 1830
Latest checkpoint’s oldestMultiXid: 1
Latest checkpoint’s oldestMulti’s DB: 1
Minimum recovery ending location: 0/0
当数据库异常停止后再重新启动时,需要做实例恢复,实例恢复的过程是从WAL日志中,找到最后一次的checkpoint点,然后读取这个点之后的WAL日志,然后重新应用这些日志,这个过程称为数据库实例的前滚恢复。最后一次的checkpoint点的信息就记录在上面“Latest checkpoint”项中。

上面中还需要关注的一个内容是“Minimum recovery ending location”。这个值与Standby库应用WAL日志有关,需要注意的是主库与备库的控制文件中的checkpoint的信息是不同的。在备库中,每replay一些WAL日志后,就会做一次checkpoint点,然后把这个checkpoint点的信息记录到控制文件中。当在备库replay一些日志后,如果有一些脏数据刷新到磁盘中后,会把产生脏数据的最新日志的位置记录到“Minimum recovery ending location”。为什么要记录呢?因为这是为了能保证恢复到一个一致点。想象一下,备库异常停机后,再启动后,如果备库马上提供只读服务(或激活成主库),但磁盘上的数据不是一个一致的数据,这时如果读备库就会读到错误的数据,所以要replay日志一直到超过“Minimum recovery ending location”位置后,才能对外提供只读服务(或激活成主库)。

最后我们来讲一下与热备份相关的三项:

Backup start location: 0/0
Backup end location: 0/0
End-of-backup record required: no
“Backup start location”与“Backup end location”记录了一个WAL日志的位置。有人可能会误认为当在主库上执行完“SELECT pg_start_backup(‘tangxxxx’);”后,控制文件中“Backup start location”就会变成当前的WAL值,实际不是这样的。

在主库上做“SELECT pg_start_backup(‘osdba201509230923’);”后,只是在主库的数据目录下生成了一个backup_label文件,此文件的内容如下:

START WAL LOCATION: 0/4000028 (file 000000010000000000000004)
CHECKPOINT LOCATION: 0/4000060
BACKUP METHOD: pg_start_backup
BACKUP FROM: master
START TIME: 2015-09-22 19:44:23 CST
LABEL: osdba201509230923
这时我们拷贝主库,拷贝出来的数据文件中就包括了backup_label文件。备库启动时,如果发现了有backup_label这个文件,就会从这个文件中记录的点开始恢复,同时备库会把此位置记录到控制文件的“Backup start location”中。

而“Backup end location:”与“End-of-backup record required”记录了备库恢复过程中的一些中间状态。

引用:
https://mp.weixin.qq.com/s/kL9ZvbzoylAW55NJu-8RPA

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值