前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >从Oracle到PostgreSQL:一文掌握Checkpoint重要概念

从Oracle到PostgreSQL:一文掌握Checkpoint重要概念

作者头像
数据和云
发布2019-07-30 17:27:56
8870
发布2019-07-30 17:27:56
举报
文章被收录于专栏:数据和云数据和云

墨墨导读:Checkpoint是数据库中重要的概念,无论在Oracle,MySQL这个概念,它主要功能是在检查点时刻,脏数据全部刷新到磁盘,以实现数据的一致性和完整性。PostgreSQL为什么要设计Checkpoint呢?跟Oracle一样,其主要目的是缩短崩溃恢复时间。PostgreSQL在崩溃恢复时会以最近的Checkpoint为基础,不断应用这之后的WAL日志。下面我们就从Oracle的角度去学习下PostgreSQL的Checkpoint。

PG检查点进程


Oracle的checkpoint进程是由单独的ckpt进程负责的,PostgreSQL也一样,有专门的checkpoint进程checkpointer,它由postmaster负责创建。作为postmaster的子进程而存在,为几大重要的后台进程之一。

从下图中,可知postmaster进程号为1962。checkpoint的进程号为1965,其父进程号为1962,即为

Kill检查点进程可以如下图可以看到,其他进程也跟着checkoint进程重启了。有点类似于系统被初始化后。可见此进程对数据一致保护的重要性。

PG检查点的类型


在xlog.h文件中,有如下代码对checkpoint进行了相应的分类:

代码语言:javascript
复制
/* These directly affect the behavior of CreateCheckPoint and subsidiaries */
#define CHECKPOINT_IS_SHUTDOWN  0x0001  /* Checkpoint is for shutdown */
#define CHECKPOINT_END_OF_RECOVERY      0x0002  /* Like shutdown checkpoint, but
                                                                                         * issued at end of WAL recovery */
 #define CHECKPOINT_IMMEDIATE    0x0004  /* Do it without delays */
#define CHECKPOINT_FORCE                0x0008  /* Force even if no activity */
#define CHECKPOINT_FLUSH_ALL    0x0010  /* Flush all pages, including those
                                                                                 * belonging to unlogged tables */
/* These are important to RequestCheckpoint */
#define CHECKPOINT_WAIT                 0x0020  /* Wait for completion */
/* These indicate the cause of a checkpoint request */
#define CHECKPOINT_CAUSE_XLOG   0x0040  /* XLOG consumption */
#define CHECKPOINT_CAUSE_TIME   0x0080  /* Elapsed time */                                                                                        
  1. CHECKPOINT_IS_SHUTDOWN(shutdown检查点):在PG实例shutdown时做的检点
  2. CHECKPOINT_END_OF_RECOVERY(recovery end检查点): 在recovery 结束阶段做的检查点,类似于shutdown检查点,只不过在WAL恢复结束时发起。
  3. CHECKPOINT_IMMEDIATE(immediate检查点):不仅仅创建检查点,而且会马上做。这类请求一般在比较紧急的情况下,需要马上获取数据库一致状态的情况下。
  4. CHECKPOINT_FORCE(force检查点):即使没有xlog变更,也会做。请求这类检查点,往往只是想得到最近的checkpoint location而已。
  5. CHECKPOINT_FLUSH_ALL(flush检查点): 当发起flush 所有pages时发起,包括那些不logging的表
  6. CHECKPOINT_WAIT (wait检查点):检查点不会马上做,但会一直等待,直到检查点完成。往往比较重要的一些操作,但不是非常紧急的,可以请求该类检查点。尤其是一些DDL操作,对数据一致性要求高于响应时间。
  7. CHECKPOINT_CAUSE_XLOG(xlog检查点):由xlog的消耗引起,产生新xlog文件。
  8. CHECKPOINT_CAUSE_TIME (time检查点):由时间elapse引起。

从上可知,PostgreSQL的checkpoint类型也很丰富,但是它比oracle的类型少些,比如增量checkpoint.

Checkpoint触发条件


以下几种情况会触发数据库操作系统做检查点操作:

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

2) 数据库shutdown

3) 数据库recovery完成

4) WAL日志量达到了触发checkpoint阈值

5) 周期性地进行checkpoint

6) 需要刷新所有脏页

checkpoint调优


如何设置调优checkpoint,设置正确的参数呢?首先我们要先了解PostgreSQL数据的同步机制。

PostgreSQL数据的同步机制

图1. 数据同步机制

整个同步机制如上图1所示。数据库的后台进程在执行用户事务时,发生的数据更改是先写入缓冲池中,对应PostgreSQL就是shared buffers。PostgreSQL的缓冲池一般设置为总内存的1/4左右,缓冲池里面的这些数据更改,在事务提交时,是无需同步写入到磁盘的。因为在事务提交时,会先写入WAL日志,有了WAL日志,就可以在异常情况下将数据恢复,保障数据安全,因此数据本身是否在提交时写入磁盘就没那么重要了。PostgreSQL是只是在需要的时候,例如脏页较多时、或一定时间间隔后,才将数据写回磁盘。

脏页处理的过程分为几个步骤。首先是由background writer将shared buffers里面的被更改过的页面(即脏页),通过调用write写入操作系统page cache。在函数BgBufferSync可以看到,PostgreSQL的background writer进程,会根据LRU链表,扫描shared buffers(实际上是每次扫描一部分),如果发现脏页,就调用系统调用write。可以通过设置bgwriter_delay参数,来控制background writer每次扫描之间的时间间隔。background writer在对一个页面调用write后,会将该页面对应的文件(实际上是表的segement,每个表可能有多个segment,对应多个物理文件)记录到共享内存的数组CheckpointerShmem->requests中,调用顺序如下:

代码语言:javascript
复制
BackgroundWriterMain -> BgBufferSync -> SyncOneBuffer -> FlushBuffer -> smgrwrite->
mdwrite-> dirty_segment-> register-> ForwardFsyncRequest

这些request最终会被checkpointer进程读取,放入pendingOpsTable,而真正将脏页回写到磁盘的操作,是由checkpointer进程完成的。checkpointer每次也会调用smgrwrite,把所有的shared buffers脏页(即还没有被background writer清理过得脏页)写入操作系统的page cache,并存入pendingOpsTable。这样pendingOpsTable存放了所有write过的脏页,包括之前background writer已经处理的脏页。随后PostgreSQL的checkpointer进程会根据pedingOpsTable的记录,进行脏页回写操作(注意每次调用fysnc,都会sync数据表的一个文件,文件中所有脏页都会写入磁盘),调用顺序如下:

代码语言:javascript
复制
CheckPointGuts->CheckPointBuffers->->mdsync->pg_fsync->fsync

如果checkpointer做磁盘写入的频率过高,则每次可能只写入很少的数据。我们知道,磁盘对于顺序写入批量数据比随机写的效率要高的多,每次写入很少数据,就造成大量随机写;而如果我们放慢checkpoint的频率,多个随机页面就有可能组成一次顺序批量写入,效率大大提高。另外,checkpoint会进行fsync操作,大量的fsync可能造成系统IO阻塞,降低系统稳定性,因此checkpoint不能过于频繁。但checkpoint的间隔也不能无限制放大。因为如果出现系统宕机,在进行恢复时,需要从上一次checkpoint的时间点开始恢复,如果checkpoint间隔过长,会造成恢复时间缓慢,降低可用性。

相关参数配置

checkpoint_warning

如果检查点触发的频率小于30s,则log日志中会提醒你增加max_wal_size。

  • 参考设置:如果硬盘的性能很好可以设置小一些,如果硬盘性能差就设置大一些。这个参数不影响性能。只是用来检查实际checkpoint发生的频率。

checkpoint_timeout

自动检查点出发的时间,增加这个参数的值会增加崩溃恢复所需的时间。取值范围为30S≈1天。磁盘性能好的话可以适当减小。这个值减小会增加检查点频率,降低性能。

max_wal_size

在自动WAL检查点使得WAL增长到最大尺寸,到了这个尺寸,检查点就开始工作。

  • 参考值:主机内存1/2,默认是1GB

min_wal_size

WAL磁盘使用率低于这个设置,旧的WAL文件总数被回收,确保预留足够的WAL空间处理WAL使用中的峰值。

  • 参考值:主机内存1/8

checkpoint_completion_target

指定检查点完成的目标,作为检查点之间总时间的一部分。默认值是0.5,这个参数一般要结合checkpoint_timeout来使用。

场景

数据量

数据写入速度(1G/s)

checkpoint_completion_target=0.5checkpoint_timeout = 30min

100G

100/(0.5*30*60)*1024≈114M/s

checkpoint_completion_target=0.9checkpoint_timeout = 30min

100G

100/(0.8*30*60)*1024≈71M/s

从上可知checkpoint_completion_target设置的越高的情况下,写入速度越低,对客户而言,体验越好,性能越高。反之,较低的值可能会引起I/O峰值,导致“卡死”的现象。

  • 参考值:0.8≈0.9

checkpoint_flush_after

单位:BLCKSZ

当checkpointer process脏数据超过配置阈值时,触发调用OS sync_file_range,告诉os backend flush线程异步刷盘。从而削减os dirty page堆积

  • 参考值:有效范围介于0(禁用强制写回)和2MB之间。Linux上的默认值为256KB,其他地方为0

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-07-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 数据和云 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档