联系管理员

开通文章发布权限

扫码 添加微信
微信图片
电话:15897897836 QQ:2106973531

checkpoint是什么东西?一个位置?还是一个操作?

checkpoint是一个操作,执行这个操作的开始时刻,会记录当前开始时刻的 WAL 位置作为重做点,这个位置会被保存在文件中。 然后将该重做点之前所有 shared buffer 中的脏页均被刷入到存储。checkpoint又名检查点,一般checkpoint会将某个时间点之前的脏数据全部刷新到磁盘,以实现数据的一致性与完整性。

1、背景

  • WAL 日志就这么一直写下去,子子孙孙无穷匮也,磁盘不炸了吗

  • 我怎么知道数据库什么时候崩的?恢复的时候,WAL 日志应该从哪开始重放呢?

  • checkpoint是什么东西?一个点吗?一个位置?还是一个操作?

2、checkpoint

checkpoint是一个操作,执行这个操作的开始时刻,会记录当前开始时刻的 WAL 位置作为重做点,这个位置会被保存在文件中。 然后将该重做点之前所有 shared buffer 中的脏页均被刷入到存储。checkpoint又名检查点,一般checkpoint会将某个时间点之前的脏数据全部刷新到磁盘,以实现数据的一致性与完整性。目前各个流行的关系型数据库都具备checkpoint功能,其主要目的是为了缩短崩溃恢复时间,以Oracle为例,在进行数据恢复时,会以最近的checkpoint为参考点执行事务前滚。PostgreSQL在崩溃恢复时会以最近的checkpoint为基础,不断应用这之后的WAL日志。
简单来说:

  • 确保数据一致性:定期将内存中的脏页写入磁盘,确保数据库的一致性。

  • 加速崩溃恢复:减少需要重放的 WAL 日志量,从而加速系统崩溃后的恢复过程。

  • 控制 WAL 日志大小:通过记录检查点,限制 WAL 日志的增长,优化存储使用。

3、怎么触发checkpoint?

分析源码,发现在src/include/access/xlog.h定义了几类触发的场景:

#define CHECKPOINT_IS_SHUTDOWN	0x0001	/* 数据库关闭 */
#define CHECKPOINT_END_OF_RECOVERY	0x0002	/* 数据库恢复结束时触发 */
#define CHECKPOINT_IMMEDIATE	0x0004	/* 立即执行检查点操作,不进行延迟 */
#define CHECKPOINT_FORCE		0x0008	/* 强制执行检查点 */
#define CHECKPOINT_FLUSH_ALL	0x0010	/* 刷新所有页面,包括未记录表的页面 */
/* 以下标志对 RequestCheckpoint 函数非常重要 */
#define CHECKPOINT_WAIT			0x0020	/* 等待检查点操作完成 */
#define CHECKPOINT_REQUESTED	0x0040	/* 已发出检查点请求 */
/* 以下标志指示检查点请求的原因 */
#define CHECKPOINT_CAUSE_XLOG	0x0080	/* XLOG日志量达到一定程度触发 */
#define CHECKPOINT_CAUSE_TIME	0x0100	/* 周期性触发 */

根据上述定义,也就是说,以下几种情况会触发PG数据库操作系统做检查点操作:

  1. 超级用户(其他用户不可)执行CHECKPOINT命令

  2. 数据库shutdown

  3. 数据库recovery完成

  4. XLOG日志量达到了触发checkpoint阈值

  5. 周期性地进行checkpoint

  6. 需要刷新所有脏页

为了能够周期性的创建检查点,减少崩溃恢复时间,同时合并I/O,PostgreSQL提供了辅助进程checkpointer。它会对不断检测周期时间以及上面的XLOG日志量阈值是否达到,而周期时间以及XLOG日志量阈值可以通过参数来设置大小,接下来介绍下与checkpoints相关的参数。

checkpoint_segments:WAL log的最大数量,系统默认值是3。超过该数量的WAL日志,会自动触发checkpoint。
checkpoint_timeout:系统自动执行checkpoint之间的最大时间间隔。系统默认值是5分钟。
checkpoint_completion_target:该参数表示checkpoint的完成时间占两次checkpoint时间间隔的比例,系统默认值是0.5,也就是说每个checkpoint需要在checkpoints间隔时间的50%内完成。
checkpoint_warning:系统默认值是30秒,如果checkpoints的实际发生间隔小于该参数,将会在server log中写入写入一条相关信息。可以通过设置为0禁用。

4、checkpoint 操作的过程

checkpoint操作执行的过程
图片#B #S #R #60% #auto

假设要执行三条insert语句

  • checkpoint 操作首先记录下 checkpoint 的开始位置,记录为 redo point(重做位点)

  • checkpoint 将 shared buffer 中的数据刷到磁盘里面去

  • 这时候数据库又来了一条 SQL insert 3

  • checkpoint 刷脏结束,redo point 之前的数据均已被刷到磁盘存储(数据1和2)

  • 每个检查点后,第一次数据页的变化会导致整个页面会被记录在XLOG日志中

这时候假如开始数据库恢复,那么数据库会从pg_control 文件中找到最新的 checkpoint 位置,再从 checkpoint 找到 redo point 的位置,开始重放日志。不难看出,1 和 2 这两个数据在 checkpoint 中已经持久化到磁盘存储,WAL 日志中也只有 INSERT 3 操作需要重放。ControlFileData结构定义了pg_control文件中存储的数据格式。这个结构位于 src/include/catalog/pg_control.h 文件中。
typedef struct ControlFileData
{
    uint32      system_identifier; /* 唯一的系统标识符,用于区分不同的数据库实例 */
    uint32      pg_control_version; /* pg_control 文件的版本号 */
    uint32      catalog_version_no; /* 数据库的目录版本号 */
    DBState     state;              /* 数据库的当前状态 */
    pg_time_t   time;               /* 最后一次更新的时间戳 */
    XLogRecPtr  checkPoint;         /* 最后一个检查点的 WAL(Write-Ahead Logging)记录指针 */
    XLogRecPtr  prevCheckPoint;     /* 上一个检查点的 WAL 记录指针 */
    CheckPoint  checkPointCopy;     /* 最后一个检查点记录的副本 */
    XLogRecPtr  unloggedLSN;        /* 当前未记录的 LSN(日志序列号) */
    // 其他字段省略
} ControlFileData; 

读取和写入 pg_control 文件的主要函数 ReadControlFileUpdateControlFile位于src/backend/access/transam/xlog.c 文件中。查看源码,发现检查点机制的主要实现位于 src/backend/postmaster/checkpointer.c 文件中。以下是一些关键函数和它们的作用:CheckpointerMain :检查点进程的主函数。

void
CheckpointerMain(void)
{
    // 初始化和设置信号处理
    pqsignal(SIGHUP, SignalHandlerForConfigReload);
    pqsignal(SIGINT, SignalHandlerForShutdownRequest);
    pqsignal(SIGTERM, SignalHandlerForShutdownRequest);
    pqsignal(SIGQUIT, SignalHandlerForCrashRequest);
    pqsignal(SIGUSR1, SignalHandlerForCheckpointRequest);
    pqsignal(SIGUSR2, SignalHandlerForCheckpointRequest);

    // 主循环
    for (;;)
    {
        // 等待检查点请求或超时
        WaitLatchOrSocket(MyLatch, WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH, -1, WAIT_EVENT_CHECKPOINTER_MAIN);

        // 处理检查点请求
        if (got_SIGHUP)
        {
            got_SIGHUP = false;
            ProcessConfigFile(PGC_SIGHUP);
        }

        if (shutdown_requested)
        {
            CreateCheckPoint(CHECKPOINT_IS_SHUTDOWN | CHECKPOINT_IMMEDIATE);
            proc_exit(0);
        }

        if (checkpoint_requested)
        {
            checkpoint_requested = false;
            CreateCheckPoint(0);
        }
    }
}

CreateCheckPoint:执行检查点操作的核心函数,负责将脏页写入磁盘并记录检查点信息。

void
CreateCheckPoint(int flags)
{
    CheckPoint  checkpoint;
    XLogRecPtr  recptr;

    // 初始化检查点结构
    MemSet(&checkpoint, 0, sizeof(CheckPoint));

    // 获取当前 WAL 位置
    recptr = GetInsertRecPtr();

    // 将脏页写入磁盘
    CheckPointBuffers(flags);

    // 记录检查点信息到 WAL 日志
    recptr = XLogInsert(RM_XLOG_ID, XLOG_CHECKPOINT_SHUTDOWN, &checkpoint);

    // 更新控制文件
    UpdateControlFile();
}

CheckPointBuffers:将脏页写入磁盘。

void
CheckPointBuffers(int flags)
{
    int num_to_write;
    int num_written;

    // 计算需要写入的脏页数量
    num_to_write = GetNumDirtyBuffers();

    // 写入脏页
    num_written = WriteDirtyBuffers(num_to_write);

    // 同步磁盘
    if (num_written > 0)
        SyncDataDirectory();
}

CheckPointWriteDelay:控制写入速率,避免 I/O 峰值。

void
CheckPointWriteDelay(int flags)
{
    static int checkpoint_write_delay = 0;

    // 计算写入延迟
    if (checkpoint_write_delay > 0)
        pg_usleep(checkpoint_write_delay);
}

5、总结

  • checkpoint中记录了 redo point,标记 redo point 之前的数据均已刷脏,完成持久化存储

  • 标记 redo point 之前的 WAL 日志可以被清理回收

  • 每个检查点后,第一次数据页的变化会导致整个页面会被记录在XLOG日志中。

  • 检查点的开销比较高,可以用checkpoint_warning自检,相应调大checkpoint_segments

  • 检查点的位置保存在文件 pg_control,pg_control文件被损坏可能会导致数据库不可用### 数据库

相关文章

从安装PostgreSQL开始
通过以下步骤,你可以在 CentOS 7 上成功安装和配置 PostgreSQL 14。首先,设置 RPM 仓库并安装 PostgreSQL 14 服务器。然后,创建自定义数据存储目录并初始化数据库。接下来,修改启动脚本以使用自定义数据存储目录,并设置 PostgreSQL 监听所有 IP 地址。为了增强安全性,配置密码认证并修改 postgres 超级用户密码。最后,确保所有配置生效,重启 PostgreSQL 服务。通过这些步骤,你将拥有一个配置良好且安全的 PostgreSQL 数据库环境。如果在过程中遇到任何问题,请参考官方文档或寻求专业支持。
checkpoint是什么东西?一个位置?还是一个操作?
checkpoint是一个操作,执行这个操作的开始时刻,会记录当前开始时刻的 WAL 位置作为重做点,这个位置会被保存在文件中。 然后将该重做点之前所有 shared buffer 中的脏页均被刷入到存储。checkpoint又名检查点,一般checkpoint会将某个时间点之前的脏数据全部刷新到磁盘,以实现数据的一致性与完整性。
PostgreSQL 内参:深入解析运行原理【快照篇】
来源于灿哥的:《PostgreSQL 内参:深入解析运行原理》,非常好的一本书。
PG存在的级联删除(ON DELETE CASCADE)
在 PostgreSQL 中,如果你有两张表:用户表(users)和订单表(orders),并且用户表的主键是订单表的外键,那么你可以通过以下步骤来进行实验,删除订单表中的一条数据,然后删除用户表中的一条数据。

评论

快捷导航

把好文章收藏到微信

打开微信,扫码查看

关闭

还没有账号?立即注册