第二章 checkpoint机制 - 介绍

2024-05-11 08:20

本文主要是介绍第二章 checkpoint机制 - 介绍,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Checkpoint介绍

1、介绍

PostgreSQL基于DRAM+HDD/SSD两层存储架构,所有读写都在DRAM中进行。由于数据写大部分都是随机的,为提高数据库性能,通过写前日志WAL将所有修改都记录到日志中,事务提交时,将日志持久化到磁盘即可,而脏数据页由后台进程异步刷写磁盘,从而将随机写转换成顺序写。

崩溃重启时通过WAL日志将修改回放出来,从而保证数据持久性和一致性,但是如果所有事务的WAL日志都需要回放的话,一旦日志量非常大时,恢复时间就会很长。为减小恢复时间,PostgreSQL通过checkpoint将脏数据刷写到磁盘,崩溃恢复时,只需将checkpoint之后的日志回放即可。

PostgreSQL由checkpoint进程完成刷写脏页(还有一个后台进程bgwriter也会刷写脏页,本文不做过多介绍),并生成一个CHECKPOINT的WAL日志,同时将checkpoint位置记录到pg_control文件中。重启恢复时,从pg_control文件中读取checkpoint位置,作为读取WAL日志和回放的起始位置。启动后可以看到checkpoint进程:

80259 ? Ss 0:00 /home/yzs/bin/postmaster -D /home/yzs/data/
80260 ? Ss 0:00 \_ postgres: logger
80262 ? Ss 0:00 \_ postgres: checkpointer
80263 ? Ss 0:00 \_ postgres: background writer
80264 ? Ss 0:00 \_ postgres: walwriter
80265 ? Ss 0:00 \_ postgres: autovacuum launcher
80266 ? Ss 0:00 \_ postgres: stats collector
80267 ? Ss 0:00 \_ postgres: autoprewarm master
80268 ? Ss 0:00 \_ postgres: logical replication launcher

当将checkpoint子进程kill -9杀掉后,其他进程也会重新启动,这也说明checkpoint子进程对数据一致性有很重要保护作用。

pg_control文件记录的checkpoint信息:

2、checkpoint相关参数

1)log_checkpoints

该参数默认关闭,开启后将每次checkpoint详细信息记录到错误日志中,可以通过此信息了解系统负载。一个相关信息如下:

“checkpoint starting: immediate force wait”//这条信息由函数LogCheckpointStart输出
“checkpoint complete: wrote 1 buffers (0.0%); 0 WAL file(s) added, 0 removed, 0 recycled; write=0.000 s, sync=0.000 s, total=0.001 s; sync files=1, longest=0.000 s, average=0.000 s; distance=0 kB, estimate=11948 kB”//这条信息由函数LogCheckpointEnd输出

2)checkpoint_warning

该参数默认30s,如果填充的WAL段文件导致检查点之间的间隔低于这个参数表示的时间,就向服务器日志写一个消息。0表示关闭警告。如果checkpoint_timeout小于checkpoint_warning值,则不会有警告产生。如果磁盘性能好,可以适当将这个值设置小点,但这个参数不会影响性能,仅用于检查检查点的频率。

3)checkpoint_timeout

自动检查点之间的最长时间。如果没有指定单位,则以秒为单位。默认值是5分钟。增加这个值,会增加崩溃恢复的时间。

checkpoint_timeout用到的位置:

  • checkpoint进程距上次检查点时间超过这个值,就强制触发检查点。在3节 checkpoint发生时机详细介绍。
  • Checkpoint进程执行完一次检查点后,如果执行的时间不够checkpoint_timeout 时间,则等待直到达到这个时间,流程简化后:
CheckpointerMainfor(;;){now = (pg_time_t) time(NULL);CreateCheckPoint(flags);//执行检查点last_checkpoint_time = now;//检查点开始时间now = (pg_time_t) time(NULL);elapsed_secs = now - last_checkpoint_time;//检查点执行的时间if (elapsed_secs >= CheckPointTimeout)continue;//检查点超时,不进行休眠cur_timeout = CheckPointTimeout - elapsed_secs;(void) WaitLatch(MyLatch,WL_LATCH_SET | WL_TIMEOUT | WL_EXIT_ON_PM_DEATH,cur_timeout * 1000L /* convert to ms */ ,WAIT_EVENT_CHECKPOINTER_MAIN);//检查点休眠}
  • 每次刷写完一个脏页后进行检查点调度判断,若刷写IO太过频繁则休息100ms
BufferSync->CheckpointWriteDelay->|-- IsCheckpointOnSchedulegettimeofday(&now, NULL);elapsed_time = ((double) ((pg_time_t) now.tv_sec - ckpt_start_time) +now.tv_usec / 1000000.0) / CheckPointTimeout;//脏页刷写率大于checkpoint消耗时间率的话,需要sleep 100msif (progress < elapsed_time){ckpt_cached_elapsed = elapsed_time;return false;}|-- pg_usleep(100000L);

 注意:IsCheckpointOnSchedule中除了判断时间的进度外,会先对日志产生的进度进行判断,从而对刷新脏页进行限速

if (RecoveryInProgress())recptr = GetXLogReplayRecPtr(NULL);//恢复场景:回放的WAL日志lsn
elserecptr = GetInsertRecPtr();//产生的WAL的lsn
elapsed_xlogs = (((double) (recptr - ckpt_start_recptr)) /wal_segment_size) / CheckPointSegments;//检查点以来产生WAL的进度
if (progress < elapsed_xlogs){ckpt_cached_elapsed = elapsed_xlogs;return false;
}

4)min_wal_size

用于回收WAL文件时设置未来日志文件段号值。段号值最小即为min_wal_size计算所得。所以只要WAL磁盘用量保持在这个设置之下,在检查点时旧的文件总是被回收以便未来使用,而不是直接删除。这个可以用来确保足够的WAL空间被保留下来应付WAL使用高峰,例如大量写任务下。如果指定时没有单位,则以MB为单位,默认80MB。

执行完checkpoint后,回收WAL文件时,用于判断回收后日志文件段号的范围:

XLOGfileslopminSegNo = RedoRecPtr / wal_segment_size +ConvertToXSegs(min_wal_size_mb, wal_segment_size) - 1;maxSegNo = RedoRecPtr / wal_segment_size +ConvertToXSegs(max_wal_size_mb, wal_segment_size) - 1;distance = (1.0 + CheckPointCompletionTarget) * CheckPointDistanceEstimate;/* add 10% for good measure. */distance *= 1.10;recycleSegNo = (XLogSegNo) ceil(((double) RedoRecPtr + distance) /wal_segment_size);if (recycleSegNo < minSegNo)recycleSegNo = minSegNo;if (recycleSegNo > maxSegNo)recycleSegNo = maxSegNo;return recycleSegNo;

 说明:回收WAL日志文件后,增加的段号要在min_wal_size和max_wal_size范围内

5)max_wal_size

自动WAL检查点之间允许WAL增长到的最大尺寸。这是一个软限制,特殊情况下WAL尺寸会超过max_wal_size。如果没有指定单位,则以MB为单位,默认1GB。增加这个参数会增加崩溃恢复时间。

在回收WAL文件时,预留的日志文件号最大是这个值计算出的段文件号。也就是说超过这量的日志需要删除。

另外就是和checkpoint_complete_target联合使用。

用到该参数的地方除了上文介绍的回收WAL日志文件处外,还用于计算CheckPointSegments值(checkpoint触发值),该值同样用于判断是否进行检查点调度。该值计算方法:

CalculateCheckpointSegmentstarget = (double) ConvertToXSegs(max_wal_size_mb, wal_segment_size) /(1.0 + CheckPointCompletionTarget);CheckPointSegments = (int) target;if (CheckPointSegments < 1)CheckPointSegments = 1;

说明:如果检查点不能立即完成,则老WAL日志就不能立即删除。max_wal_size规定了WAL日志的最大值。达到WAL日志大小的顶峰是checkpoint即将执行完成的时刻,因为此时包含这次触发的WAL日志加上新增的WAL日志。假设触发值是target,则checkpoint_timeout时间内,WAL日志新增大小最多为target。假设WAL日志增长速度相同,则此时增长的日志大小为target*checkpoint_completion_target,为保证峰值,wal日志大小是max_wal_size,由此可以计算出触发值:

target+target*checkpoint_completion_target=max_wal_size
target=max_wal_size/(1+checkpoint_completion_target)

6)checkpoint_completion_target

该参数表示checkpoint的完成时间占两次checkpoint时间间隔的比例,默认值是0.5,也就是说每个checkpoint需要在checkpoint时间间隔checkpoint_timeout的50%内完成。Checkpoint执行会消耗大量系统资源,尤其时IO资源,需要对IO进行限速以减少系统影响,使得磁盘IO变得平缓。

这个值除了在计算WAL日志大小触发checkpoint阈值(上小节介绍)、计算回收日志后最大段号(min_wal_size部分介绍)外,还在判断是否进行checkpoint调度时用到:

IsCheckpointOnScheduleprogress *= CheckPointCompletionTarget;//将刷脏页率缩放后,用于后续判断....

7)checkpoint_flush_after

自动上次checkpoint以来刷写了这么多脏页后,发起sync操作。这样做限制操作系统缓冲中脏页数量,降低checkpoint末尾发出sync或者OS在后台大批量写回数据时被卡住的可能性。如果没有指定单位,默认是页数,指定MB则转换成页数。

由函数ScheduleBufferTagForWriteback进行sync调度。

SyncOneBufferFlushBuffer(bufHdr, NULL);//刷写一个脏页tag = bufHdr->tag;ScheduleBufferTagForWriteback(wb_context, &tag);//调度是否sync|--	if (*context->max_pending > 0){//将脏页sync请求放入请求队列pending = &context->pending_writebacks[context->nr_pending++];pending->tag = *tag;}if (context->nr_pending >= *context->max_pending)IssuePendingWritebacks(context);//若请求数>=checkpoint_flush_after则sync//context->max_pending来自checkpoint_flush_afterBufferSync->WritebackContextInit(&wb_context, &checkpoint_flush_after);context->max_pending = max_pending;context->nr_pending = 0;

3、checkpoint发生时机

Checkpoint触发时机分为以下多种:

1)时间触发:后台checkpoint进程,距上次执行时间超过checkpoint_timeout值就会触发。由时间超时触发的时机:

CheckpointerMain:for (;;){now = (pg_time_t) time(NULL);elapsed_secs = now - last_checkpoint_time;//距上次检查点时间if (elapsed_secs >= CheckPointTimeout){//超过checkpoint_timeoutdo_checkpoint = true;flags |= CHECKPOINT_CAUSE_TIME;//发起CHECKPOINT_CAUSE_TIME的检查点}if (do_checkpoint){CreateCheckPoint(flags);last_checkpoint_time = now;//checkpoint开始时间}...}

2)数据库正常关闭时,触发一次:

CheckpointerMainpqsignal(SIGUSR2, ReqShutdownHandler);/* 注册信号处理函数 */for (;;){if (shutdown_requested){//checkpoint进程接收到shutdown请求ExitOnAnyError = true;ShutdownXLOG(0, 0);|--	CreateCheckPoint(CHECKPOINT_IS_SHUTDOWN | CHECKPOINT_IMMEDIATE);proc_exit(0);}...}
//接收到信号SIGUSR2后,发起shutdown checkpoint
static void ReqShutdownHandler(SIGNAL_ARGS)
{int			save_errno = errno;shutdown_requested = true;SetLatch(MyLatch);errno = save_errno;
}

3)数据库崩溃恢复,修复完成后触发一次:

StartupXLOG//为恢复进程CreateCheckPoint(CHECKPOINT_END_OF_RECOVERY | CHECKPOINT_IMMEDIATE);

4)手动执行CHECKPOINT命令

5)基础备份:当进行数据库基础备份时,会执行pg_start_backup->do_pg_start_backup触发一次:

do_pg_start_backupRequestCheckpoint(CHECKPOINT_FORCE | CHECKPOINT_WAIT |(fast ? CHECKPOINT_IMMEDIATE : 0));

6)每次将日志XLogWrite写入磁盘并且一个WAL日志文件写满后,自从上次checkpoint以来产生的超过max_wal_size放大checkpoint_completion_target后触发一次:

XLogWriteif (finishing_seg){//写满一个WAL段文件if (IsUnderPostmaster && XLogCheckpointNeeded(openLogSegNo)){(void) GetRedoRecPtr();if (XLogCheckpointNeeded(openLogSegNo))RequestCheckpoint(CHECKPOINT_CAUSE_XLOG);}}
//判断WAL自从上次checkpoint以来产生量是否超过阈值
static bool XLogCheckpointNeeded(XLogSegNo new_segno)
{XLogSegNo	old_segno;XLByteToSeg(RedoRecPtr, old_segno, wal_segment_size);if (new_segno >= old_segno + (uint64) (CheckPointSegments - 1))return true;return false;
}
//其中CheckPointSegments来自函数CalculateCheckpointSegments,由max_wal_size放大
//checkpoint_completion_target倍后计算得来,在第2节的max_wal_size中介绍。

4、checkpoint监控

除了log_checkpoints监听日志的方式外,还可以通过pg_stat_bgwriter视图查看checkpoint。下面介绍与checkpoint相关的列:

checkpoints_timed

因为时间触发的次数

checkpoints_req

其他原因触发的次数

checkpoint_write_time

缓存刷写到文件系统cache花费的时间

checkpoint_sync_time

缓存对应的文件系统cache刷写到磁盘花费的时间

buffers_checkpoint

buffer刷新到磁盘的数目

buffers_backend

checkpoint接收到sync请求次数

buffers_backend_fsync

后台因为发送sync请求失败,需要自身执行fsync操作的次数

stats_reset

更新时间

这篇关于第二章 checkpoint机制 - 介绍的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/979001

相关文章

Maven 配置中的 <mirror>绕过 HTTP 阻断机制的方法

《Maven配置中的<mirror>绕过HTTP阻断机制的方法》:本文主要介绍Maven配置中的<mirror>绕过HTTP阻断机制的方法,本文给大家分享问题原因及解决方案,感兴趣的朋友一... 目录一、问题场景:升级 Maven 后构建失败二、解决方案:通过 <mirror> 配置覆盖默认行为1. 配置示

MybatisPlus service接口功能介绍

《MybatisPlusservice接口功能介绍》:本文主要介绍MybatisPlusservice接口功能介绍,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友... 目录Service接口基本用法进阶用法总结:Lambda方法Service接口基本用法MyBATisP

Redis过期删除机制与内存淘汰策略的解析指南

《Redis过期删除机制与内存淘汰策略的解析指南》在使用Redis构建缓存系统时,很多开发者只设置了EXPIRE但却忽略了背后Redis的过期删除机制与内存淘汰策略,下面小编就来和大家详细介绍一下... 目录1、简述2、Redis http://www.chinasem.cn的过期删除策略(Key Expir

Go语言中Recover机制的使用

《Go语言中Recover机制的使用》Go语言的recover机制通过defer函数捕获panic,实现异常恢复与程序稳定性,具有一定的参考价值,感兴趣的可以了解一下... 目录引言Recover 的基本概念基本代码示例简单的 Recover 示例嵌套函数中的 Recover项目场景中的应用Web 服务器中

MySQL复杂SQL之多表联查/子查询详细介绍(最新整理)

《MySQL复杂SQL之多表联查/子查询详细介绍(最新整理)》掌握多表联查(INNERJOIN,LEFTJOIN,RIGHTJOIN,FULLJOIN)和子查询(标量、列、行、表子查询、相关/非相关、... 目录第一部分:多表联查 (JOIN Operations)1. 连接的类型 (JOIN Types)

java中BigDecimal里面的subtract函数介绍及实现方法

《java中BigDecimal里面的subtract函数介绍及实现方法》在Java中实现减法操作需要根据数据类型选择不同方法,主要分为数值型减法和字符串减法两种场景,本文给大家介绍java中BigD... 目录Java中BigDecimal里面的subtract函数的意思?一、数值型减法(高精度计算)1.

Pytorch介绍与安装过程

《Pytorch介绍与安装过程》PyTorch因其直观的设计、卓越的灵活性以及强大的动态计算图功能,迅速在学术界和工业界获得了广泛认可,成为当前深度学习研究和开发的主流工具之一,本文给大家介绍Pyto... 目录1、Pytorch介绍1.1、核心理念1.2、核心组件与功能1.3、适用场景与优势总结1.4、优

Java实现本地缓存的常用方案介绍

《Java实现本地缓存的常用方案介绍》本地缓存的代表技术主要有HashMap,GuavaCache,Caffeine和Encahche,这篇文章主要来和大家聊聊java利用这些技术分别实现本地缓存的方... 目录本地缓存实现方式HashMapConcurrentHashMapGuava CacheCaffe

Jvm sandbox mock机制的实践过程

《Jvmsandboxmock机制的实践过程》:本文主要介绍Jvmsandboxmock机制的实践过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、背景二、定义一个损坏的钟1、 Springboot工程中创建一个Clock类2、 添加一个Controller

Spring Security介绍及配置实现代码

《SpringSecurity介绍及配置实现代码》SpringSecurity是一个功能强大的Java安全框架,它提供了全面的安全认证(Authentication)和授权(Authorizatio... 目录简介Spring Security配置配置实现代码简介Spring Security是一个功能强