在PostgreSQL中,检查点进程(后台)会执行检查点;当下列情形之一发生时,它会启动处理:
- 距离上次检查点已经过去了由参数
checkpoint_timeout
配置的时间间隔(默认间隔为300秒(5分钟))。 - 在9.4及以前的版本中,自上一次检查点以来消耗的WAL段文件超出了参数
checkpoint_segments
的数量(默认值为3)。 - 在9.5及以后的版本,
pg_xlog
(10之后是pg_wal
)中的WAL段文件总大小超过参数max_wal_size
配置的值(默认值为1GB,64个段文件)。 - PostgreSQL服务器以
smart
或fast
模式关闭。
当超级用户手动执行CHECKPOINT
命令时,该进程也会启动。
在9.1或更早的版本中,后台写入进程(见8.6节)同时负责脏页写入与检查点。
在接下来的几个小节中会简要描述检查点过程与pg_control
文件,pg_control
文件保存了当前检查点的元数据。
9.7.1 检查点过程概述
检查点进程负责两个方面:为数据库恢复做准备工作,以及共享缓冲池上脏页的刷盘工作。在本小节介绍其内部过程时,将重点关注前一个方面。参见图9.13和以下描述。
图9.13 PostgreSQL检查点的内部流程
- 当检查点进程启动时,会将重做点(REDO Point) 存储在内存中;重做点 是上次检查点开始时刻时XLOG记录的写入位置,也是数据库恢复的开始位置。
- 该检查点相应的XLOG记录(即检查点)会被写入WAL缓冲区,该记录的数据部分是由
CheckPoint
结构体定义的,包含了一些变量,比如第一步中重做点的位置。另外,写入检查点记录的位置,也按照字面意义叫做检查点(checkpoint )。 - 共享内存中的所有数据(例如,CLOG的内容)都会被刷入持久存储中。
- 共享缓冲池中的所有脏页都会被逐渐刷写到存储中。
- 更新
pg_control
文件,该文件包含了一些基础信息,例如上一次检查点的位置,后面会介绍该文件的细节
typedef struct CheckPoint
{
XLogRecPtr redo; /* 当创建存盘时,下一个可用的RecPtr(即重做点) */
TimeLineID ThisTimeLineID; /* 当前时间线ID TLI */
TimeLineID PrevTimeLineID; /* 前一个时间线ID TLI, 如果当前记录开启了一条新的时间线
* (其他情况下等于ThisTimeLineID) */
bool fullPageWrites; /* 当前全页写入的状态 */
uint32 nextXidEpoch; /* 下一个时事务ID(nextXid)的高位bit */
TransactionId nextXid; /* 下一个空闲事务ID */
Oid nextOid; /* 下一个空闲OID */
MultiXactId nextMulti; /* 下一个空闲MultiXactId */
MultiXactOffset nextMultiOffset;/* 下一个空闲MultiXact 偏移量 */
TransactionId oldestXid; /* 集蔟范围最小的datfronzenxid */
Oid oldestXidDB; /* 带有最小datfrozenxid的数据库 */
MultiXactId oldestMulti; /* 集蔟范围内最小的datminmxid */
Oid oldestMultiDB; /* 带有最小datminmxid的数据库 */
pg_time_t time; /* 存盘的时间戳 */
/* 最老的仍然在运行的事务ID,只有当从在线检查点中初始化一个热备时才会需要该字段。因此只有
* 当在线检查点且wal_level配置为热备时我们才会费劲计算这个字段。其他情况下会被设置为
* InvalidTransactionId */
TransactionId oldestActiveXid;
} CheckPoint;
让我们从数据库恢复的角度来总结上面的内容,检查点过程会创建包含重做点的检查点,并将检查点位置与其他信息存储到pg_control
文件中。因此,PostgreSQL能够通过从重做点回放WAL数据来进行恢复(重做点是从检查点中获取的)。
9.7.2 pg_crontrol
文件
由于pg_control
文件包含了检查点的基本信息,因此它对于数据库恢复肯定是必不可少的。如果它被破坏或不可读,因为系统不知道从哪里开始恢复,则恢复过程就无法启动。
尽管pg_control
文件存储了40多条数据项,如下三个是接下来和我们讨论内容相关的:
- 状态(State) —— 最近检查点过程开始时数据库的状态,总共有七种状态:
start up
表示系统正在启动,shut down
表示系统被关机命令正常关闭,in production
表示数据库正在运行,诸如此类。 - 最新检查点位置(Latest Checkpoint Location) —— 最新检查点的LSN位置
- 上次检查点位置(Prior Checkpoint Location) —— 前一个检查点的LSN位置,在版本11中已经弃用,细节如引文所示。
pg_control
文件存储在数据目录中global
子目录内;可以使用pg_controldata
程序显示其内容。
PostgreSQL11中移除了前任检查点
PostgreSQL 11及后续版本只会存储包含最新检查点或更新版本的WAL段文件;将不会存储包含先前检查点的旧段文件,以减少用于在
pg_xlog(pg_wal)
子目录下保存WAL段文件的磁盘空间。 详细信息请参见此主题。
下一节:PostgreSQL的恢复功能基于重做日志(REDO log)实现。如果数据库服务器崩溃,PostgreSQL通过从REDO点依序重放WAL段文件中的XLOG记录来恢复数据库集群。