暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Postgresql控制文件专题

概述

PostgreSQL的控制文件记录了数据库的重要信息, 如数据库的系统标识符“system_identifier”、 系统表版本“Catalog version number”、 实例状态、 Checkpoint信息、 数据页的块大小、 WAL日志的页大小及文件大小、 一些实例备份和恢复信息等。
所以PostgreSQL的控制文件与Oracle数据库的控制文件的作用基本相同, 都是记录数据库的重要信息, 只是在细节上有所不同, PostgreSQL的控制文件没有Oracle数据库中的那么复杂。

在PostgreSQL中提供了pg_controldata命令显示控制文件中的内容:

osdba-mac:~ osdba$ pg_controldata
pg_control version number: 1002
Catalog version number: 201707211
Database system identifier: 6531601841114581486
Database cluster state: in production
pg_control last modified: Mon Nov 26 15:35:41 2018
Latest checkpoint location: 2/5DB47D48
Prior checkpoint location: 2/5DB42E90
Latest checkpoint's REDO location: 2/5DB47D10
Latest checkpoint's REDO WAL file: 00000001000000020000005D
Latest checkpoint's TimeLineID: 1
Latest checkpoint's PrevTimeLineID: 1
Latest checkpoint's full_page_writes: on
Latest checkpoint's NextXID: 0:4000
Latest checkpoint's NextOID: 56205
Latest checkpoint's NextMultiXactId: 1
Latest checkpoint's NextMultiOffset: 0
Latest checkpoint's oldestXID: 548
Latest checkpoint's oldestXID's DB: 1
Latest checkpoint's oldestActiveXID: 4000
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: Mon Nov 26 15:35:38 2018
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
wal_level setting: replica
wal_log_hints setting: off
max_connections setting: 100
max_worker_processes setting: 8
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
Float4 argument passing: by value
Float8 argument passing: by value
Data page checksum version: 0
Mock authentication nonce:
73be4963d7bef303c8a6fd8924270c65137fd18d3ec7db097388565d7fc782f8

数据库的唯一标识串

数据库的唯一标识串“Database system identifier”用于唯一标识一套数据库系统, 物理复制的主数据库和备数据库有相同的数据库唯一标识串。
数据库的唯一标识串是在Initdb初始化数据库实例时生成的, 它是一个64bit的整数。
该整数由当前的时间戳和执行Initdb进程的PID的两个部分组成, 生成的算法可参见PostgreSQL源码xlog.c中的BootStrapXLOG函数, 内容如下:

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

从上面的算法中我们可以知道, 高44位的时间戳中由于取了时间戳的微秒部分, 所以重复的概率极低。
低12位是进程PID。

根据上面的原理我们就可以知道, 如果知道了PostgreSQL数据库的唯一标识串(见pg_controldata命令打印的Database system identifier部分), 就能知道该数据库是什么时候创建的, 我们可以用下面的SQL语句把唯一标识串中的时间戳取出来:

SELECT to_timestamp(((6531601841114581486>>32) & (2^32 -1)::bigint));

实际执行效果如下:

osdba-mac:~ osdba$ psql psql (10.5) Type "help" for help. osdba=# SELECT to_timestamp(((6531601841114581486>>32) & (2^32 -1)::bigint)); to_timestamp ------------------------ 2018-03-11 16:31:00+08 (1 row)

Checkpoint信息

什么是检查点(Checkpoint)?

可以想象一个场景: 如果WAL重做日志可以无限地增大, 如果仅从不丢失数据的角度来看是不需要把缓冲池中的脏数据块写入磁盘的, 因为当发生宕机时, 完全可以通过WAL重做日志来恢复整个数据库系统中的数据到宕机发生的时刻。

但这种想法明显存在以下几个问题:

  • WAL重做日志不可以无限增大, 因为WAL日志会占用一定的空间。
  • 重放WAL日志会占用时间, 不可能一个数据库宕机后我们花费很长时间来进行恢复, 通常需要在有限的时间内完成恢复, 如在几分钟之内完成。
  • 缓冲区不可能无限大, 所以不管怎么样, 都需要把一定的脏数据刷新到磁盘中, 需要考虑必须要先刷新哪些脏数据等问题。

应用检查点技术就是为了解决这些问题。
当恢复数据库时, 不需要把所有的WAL日志全部重新应用, 只需要应用某个时间点之后的WAL日志应用就可以了, 当然要做到这一点, 就需要把这一时间点之前产生的脏数据全部刷新到磁盘中, 所以检查点只是一个数据库事件, 该事件触发后将会执行一个操作, 而此操作可以保证把事件之前的脏数据全部刷新到磁盘中。
当然, 我们让Checkpoint发生得越频繁, 在数据库实例宕机后重放的WAL日志量就越少, 当然重做的日志量的多少也取决于发生宕机的时间点, 发生宕机的时间点越靠近最后的检查点, 重做的日志量也就越少。

我们通过pg_controldata命令看到控制文件中关于Checkpoint的信息有以下几项:

Latest checkpoint location: 2/5DB47D48
Prior checkpoint location: 2/5DB42E90
Latest checkpoint's REDO location: 2/5DB47D10
Latest checkpoint's REDO WAL file: 00000001000000020000005D

“Latest checkpoint location”和“Prior checkpoint location”这两项容易理解, 就是“最后一次的Checkpoint位置”和“前一次的Checkpoint位置”, 但当看到“Latest checkpoint’s REDO location”中也有一个Checkpoint的位置时就让人疑惑了: “Latest checkpoint location”“Latest checkpoint’s REDO location”为什么有两个“最后的Checkpoint位置”?

为了讲明白这个问题, 我们需要简单介绍一下发生Checkpoint的操作过程, 虽然Checkpoint事件是一个时间点, 但执行Checkpoint刷盘的操作是需要进行一段时间的,如现在我们要开始做Checkpoint了, 先记录当前点, 该当前点就记录在“Latest checkpoint’sREDO location”中, 当完成刷盘操作之后, 把Checkpoint相关信息也生成一条WAL记录,再把这条WAL记录也写入WAL日志文件中, 此WAL日志的位置就是“Latest checkpoint location:2/5DB47D48”, 然后更新控制文件中有关Checkpoint的信息。

从上面的分析中我们知道, 在数据库实例宕机之后, 开始重做WAL日志时, 开始的日志点为“Latest checkpoint’s REDO location”, 而不是“Latest checkpoint location”, 而“Latest checkpoint location”指向的是WAL日志中的一条Checkpoint的WAL记录, 这条记录中记录了本次Checkpoint事件的一些信息。

与Standby相关的信息

如果我们用pg_controldata显示备库的控制文件会发现以下两项不同,
在主库中下面这两项都是“0/0”和“0”:

Minimum recovery ending location: 0/0
Min recovery ending loc's timeline: 0

而在备库中这两项不为“0”, 示例如下:

Minimum recovery ending location: 0/271E81A8
Min recovery ending loc's timeline: 1

这两项是做什么的呢? 下面我们解释一下。
我们知道备库在不停地应用WAL日志, 对于Hot Standby, 在应用WAL日志的同时,还会对外提供服务。
备库本身也可能因断电或其他故障而宕机, 当备库在重新启动时, 不能一启动就对外提供只读服务, 因为这时的数据可能还不一致, 如果这时提供只读服务,用户会读到不一致的数据。
这两个参数用于指定当备库异常终止再启动时, 只有应用WAL日志超过指定点之后才能对外提供只读服务。 而有人可能会问, 为什么在主库上不需要这两项内容呢?
因为在主库上, 只有把当前所有的WAL日志全部应用完成之后才能对外提供服务, 而备库是不断地从主库接收日志, 然后不断地应用日志, 没有把当前WAL日志应用完的说法, 所以在备库上需要知道应用多少日志之后就可以对外提供只读服务了。

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

文章被以下合辑收录

评论