PgSQL · 特性分析 · full page write 机制

PG默认每个page的大小为8K,PG数据页写入是以page为单位,但是在断电等情况下,操作系统往往不能保证单个page原子地写入磁盘,这样就极有可能导致部分数据块只写到4K(操作系统是一般以4K为单位),这些“部分写”的页面包含新旧数据的混合。在崩溃后的恢复期间,xlog 里面存储的记录变化信息不够完整,无法完全恢复该页。PG为了解决这类问题,full_page_write机制孕育而生。

什么是full_page_write?

PostgreSQL 在 checkpoint 之后在对数据页面的第一次写的时候会将整个数据页面写到 xlog 里面。当出现主机断电或者OS崩溃时,redo操作时通过checksum发现“部分写”的数据页,并将xlog中保存的这个完整数据页覆盖当前损坏的数据页,然后再继续redo就可以恢复整个数据库了。
除了能够解决断电等带来坏数据页问题外,full_page_write 还应用在在线备份功能上。PG进行全量备份数据库一般通过pg_basebackup工具实现,pg_basebackup类似于copy操作,在此期间,也会出现部分数据页写到一半时文件被copy走了,正是因为full_page_write存在,备份出来的数据库才可以成功恢复启动。所以即便full_page_write=off,在备份时也会被强制自动打开,保证备份成功。

实现原理

full_page_write主要在XLogInsert(插入一条xlog记录)时发挥作用,通过full_page_writer开关状态以及是否是checkpoint后对数据页面的第一次修改(lsn<RedoRecPtr)判断是否需要备份数据页。如果需要备份,那么则把数据页存放在这条记录的末尾,最终写入到xlog中。

doPageWrites = Insert->fullPageWrites || Insert->forcePageWrites;
/* Find info for buffer */
for (i = 0; i < XLR_MAX_BKP_BLOCKS; i++)
{
    if (dtbuf[i] == InvalidBuffer)
    {
    	/* OK, put it in this slot */
    	dtbuf[i] = rdt->buffer;
    	if (doPageWrites && XLogCheckBuffer(rdt, true,&(dtbuf_lsn[i]), &(dtbuf_xlg[i])))
    	{
    		dtbuf_bkp[i] = true;
    		rdt->data = NULL;
    		rdt->len = 0;
    	}
    	break;
    }
    ......
}

在redo恢复的时候只要数据块有备份,那么就是用备份的数据。

/* If we have a full-page image, restore it and we're done */
if (record->xl_info & XLR_BKP_BLOCK(0))
{
	(void) RestoreBackupBlock(lsn, record, 0, false, false);
	return;
}

full_page_write不足之处

因为full_page_write需要在xlog中记录数据页,会写更多xlog文件,不仅有数据变化信息,还有数据页本身信息,这样会增加额外的IO和磁盘消耗,同时也会引起主备延迟变大。
为了优化full_page_write,社区提供了一个patch,它的主要设计是创建两个共享内存块队列,checkpoint专用buffer队列和非checkpoint专用buffer队列,同时关闭full_page_write。当用户DML产生的数据buffer需要刷盘时,并不是立即刷到磁盘,而是先进入double write的buffer队列,当buffer队列满时,则将buffer队列里面的数据首先刷到特别的double write文件,然后再将数据刷到数据库文件。通过这种设计就不需要在checkpoint 之后在对数据页面的第一次写的时候会将整个数据页面写到 xlog 里面。当数据库需要恢复的时候,遍历所有double write文件里面的记录块,找到每个记录块对应的数据库page,然后对这个page进行checksum,如果page损坏,那么直接把记录块里面的内容覆盖到buffer数据。最后把double write文件删除,重新初始化buffer队列。

总结

把full_page_write这个选项关闭会提高数据库执行速度以及减少xlog数量,但是可能导致系统崩溃或者掉电之后的数据库损坏。如果有减小部分页面写入风险的硬件支持(比如电池供电的磁盘控制器),或者文件系统支持(能够保证page写入原子性),可以把风险降低到一个可以接受的范围,那么可以考虑关闭这个选项,其他情况下建议打开这个选择。

时间: 2024-09-20 16:39:40

PgSQL · 特性分析 · full page write 机制的相关文章

PgSQL · 特性分析 · checkpoint机制浅析

背景 上期月报PgSQL · 特性分析 · Write-Ahead Logging机制浅析中简单介绍了PostgreSQL中WAL机制,其中讲到如果是创建checkpoint会触发刷新xlog日志页到磁盘,本文主要分析下PostgreSQL中checkpoint机制. checkpoint又名检查点,一般checkpoint会将某个时间点之前的脏数据全部刷新到磁盘,以实现数据的一致性与完整性.目前各个流行的关系型数据库都具备checkpoint功能,其主要目的是为了缩短崩溃恢复时间,以Oracl

PgSQL · 特性分析 · 数据库崩溃恢复(下)

背景 在上期月报PgSQL · 特性分析 · 数据库崩溃恢复(上),我们分析了PostgreSQL在数据库非正常退出后(包括通过recovery.conf用户主动恢复)的处理,概括起来分为以下几步: 1.如果满足以下条件之一,则进行非正常退出恢复 pg_control文件中的数据库状态不正常(非DB_SHUTDOWNED) pg_control文件中记录的最新检查点读取不到XLOG日志文件 2.用户指定recovery.conf文件主动恢复3.根据pg_control.backup_label确

PgSQL · 特性分析 · 数据库崩溃恢复(上)

背景 为了合并I/O提高性能,PostgreSQL数据库引入了共享缓冲区,当数据库非正常关闭,比如服务器断电时,共享缓冲区即内存中的数据就会丢失,这个时候数据库操作系统重启时就需要从非正常状态中恢复过来,继续提供服务.本文将具体分析在这种情况下,PostgreSQL数据库如何从崩溃状态中恢复. 上期月报PgSQL · 特性分析 · checkpoint机制浅析中介绍了PostgreSQL中的checkpoint机制.其中提到,当PostgreSQL数据库崩溃恢复时,会以最近的checkpoint

PgSQL · 特性分析 · MVCC机制浅析

背景 我们在使用PostgreSQL的时候,可能会碰到表膨胀的问题(关于表膨胀可以参考之前的月报),即表的数据量并不大,但是占用的磁盘空间比较大,查询比较慢.为什么PostgreSQL有可能发生表膨胀呢?这是因为PostgreSQL引入了MVCC机制来保证事务的隔离性,实现数据库的隔离级别. 在数据库中,并发的数据库操作会面临脏读(Dirty Read).不可重复读(Nonrepeatable Read).幻读(Phantom Read)和串行化异常等问题,为了解决这些问题,在标准的SQL规范中

PgSQL · 特性分析 · Write-Ahead Logging机制浅析

WAL机制简介 WAL即 Write-Ahead Logging,是一种实现事务日志的标准方法.WAL 的中心思想是先写日志,再写数据,数据文件的修改必须发生在这些修改已经记录在日志文件中之后.采用WAL日志的数据库系统在事务提交时,WAL机制可以从两个方面来提高性能: 多个client写日志文件可以通过一次 fsync()来完成 日志文件是顺序写的,同步日志的开销要远比同步数据页的开销要小 总体来说,使用了WAL机制之后,磁盘写操作只有传统的回滚日志的一半左右,大大提高了数据库磁盘I/O操作的

PgSQL · 特性分析· JIT 在数据仓库中的应用价值

背景 近几年,分析型数据库中有项技术得到了广泛的应用.它就是 JIT(Just-in-time compilation)动态编译.还有一些相关名词 LLVM codegen 和这项技术相关.本文把这项技术做一个简单的分析,和大家分享. 一.JIT 是什么 长久以来数据仓库都是以高效的处理量数据的能力著称.随着硬件的发展,他们使用大量相关技术充分挖掘硬件的能力提高数据的吞吐量和处理效率.例如 SMP MPP mapreduce 列存储 压缩 等等.这么多年开源生态的活跃,使得我们对这类技术的实现细

PgSQL · 特性分析 · 时间线解析

"时间线"(Timeline)是PG一个很有特色的概念,在备份恢复方面的文档里面时有出现.但针对这个概念的详细解释却很少,也让人不太好理解,我们在此仔细解析一下. 时间线的引入 为了理解引入时间线的背景,我们来分析一下,如果没有时间线,会有什么问题?先举个将数据库恢复到以前时间点的例子.假设在一个数据库的运行过程中,DBA在周三12:00AM删掉了一个关键的表,但是直到周五中午才发现这个问题.这个时候DBA拿出最初的数据库备份,加上存在归档目录的日志文件,将数据库恢复到周三11:00A

PgSQL · 特性分析 · 备库激活过程分析

前言 PostgreSQL standby 可以通过两种方法来激活成为主库: trigger file,配置在recovery.conf中. pg_ctl promote发送SIGUSR1信号给postmaster进程. 同时,PostgreSQL支持快速激活(fast promote)和非快速激活(fallback promote): fast promote 开启数据库读写前,不需要做检查点.而是推到开启读写之后执行一个CHECKPOINT_FORCE检查点. fallback_promot

PgSQL · 特性分析 · PostgreSQL 9.6 让多核并行起来

背景 经过多年的酝酿(从支持work process到支持动态fork共享内存,再到内核层面支持并行计算),PostgreSQL 的多核并行计算功能终于在2016年发布的9.6版本中正式上线,为PG的scale up能力再次拔高一个台阶,标志着开源数据库已经攻克了并行计算的难题. 相信有很多小伙伴已经开始测试了. 在32物理核的机器上进行了测试,重计算的场景,性能程线性提升. 目前并行计算支持全表扫描,JOIN,聚合. 一.快速安装PostgreSQL 9.6 为了让大伙能够快速用上9.6,以下