PostgreSQL full_page_write机制

本文涉及的产品
云原生数据库 PolarDB MySQL 版,通用型 2核4GB 50GB
云原生数据库 PolarDB PostgreSQL 版,标准版 2核4GB 50GB
简介:

title: PgSQL · 特性分析· full_page_write机制

author: 康贤

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

    doPageWrites = Insert->fullPageWrites || Insert->forcePageWrites;

    len = 0;
    for (rdt = rdata;;)
    {
        if (rdt->buffer == InvalidBuffer)
        {
            /* Simple data, just include it */
            len += rdt->len;
        }
        else
        {
            /* Find info for buffer */
            for (i = 0; i < XLR_MAX_BKP_BLOCKS; i++)
            {
                if (rdt->buffer == dtbuf[i])
                {
                    /* Buffer already referenced by earlier chain item */
                    if (dtbuf_bkp[i])
                    {
                        rdt->data = NULL;
                        rdt->len = 0;
                    }
                    else if (rdt->data)
                        len += rdt->len;
                    break;
                }
                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;
                    }
                    else if (rdt->data)
                        len += rdt->len;
                    break;
                }
            }
            if (i >= XLR_MAX_BKP_BLOCKS)
                elog(PANIC, "can backup at most %d blocks per xlog record",
                     XLR_MAX_BKP_BLOCKS);
        }
        /* Break out of loop when rdt points to last chain item */
        if (rdt->next == NULL)
            break;
        rdt = rdt->next;
    }

在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;
    }

fullpagewrite

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队列。

fullpagewrite_2_

总结

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

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
3月前
|
Oracle 关系型数据库 MySQL
一文了解PostgreSQL MVCC机制
一文了解PostgreSQL MVCC机制
175 0
|
关系型数据库 PostgreSQL
PostgreSQL VFD机制
PostgreSQL VFD机制
119 0
PostgreSQL VFD机制
|
存储 关系型数据库 Go
深入理解 PostgreSQL 中的 MVCC(多版本并发控制)机制
深入理解 PostgreSQL 中的 MVCC(多版本并发控制)机制
247 0
|
关系型数据库 数据库 PostgreSQL
PostgreSQL 的事务管理和并发控制机制解析
PostgreSQL 的事务管理和并发控制机制解析
292 0
|
关系型数据库 PostgreSQL
PostgreSQL pg_resetwal处理机制
PostgreSQL pg_resetwal处理机制
177 0
|
存储 算法 安全
SHA-1被攻破了吗? PostgreSQL SCRAM-SHA-256 安全认证机制解救你来了
标签 PostgreSQL , 认证方法 , SCRAM-SHA-256 , scram , scram-sha-256-plus , SASL , Simple Authentication and Security Layer 背景 PostgreSQL的很多设计非常的工业化,比如开放了许多扩展接口(类型、操作符、索引、扫描、采样、数据库编程语言等)。
6850 0
|
存储 SQL Oracle
再谈PostgreSQL的膨胀和vacuum机制及最佳实践
作者介绍 朱贤文,成都文武信息技术有限公司创始人,PostgreSQL中国用户会核心组成员,熟悉数据库,存储和集群技术; 成都文武信息技术有限公司是PostgreSQL和GreenPlum数据库服务的专业厂商,主要产品是ECOX集群管理系统和Hunghu Cloud,专门运行数据库的私有云系统,带高端存储功能。公司总部位于天府软件园。公司网站:w3.ww-it.cn 写本文的原因 这两天有两篇专门介绍PostgreSQL的vacuum机制的技术文章,得到了比较热烈和正面的反馈,让用户可以比较清楚地理解和使用这个特性。 我个人觉得有点小遗憾:这两篇文章没有跳出技术的角度,分析为什么会有这
420 0
|
关系型数据库 数据库 C语言
|
SQL 关系型数据库 PostgreSQL
浅析PostgreSQL事务处理机制
1、Q:PostgreSQL中DDL支不支持事务? A:支持。PostgreSQL中对DDL的处理方式和普通的DML类似,也是支持事务的。
1292 0
|
SQL 监控 关系型数据库
浅析PostgreSQL事务处理机制
前段时间在公司小范围做了一个关于PG事务实现的讲座,最后总结了一个摘要性的东西,分享一下,欢迎拍砖。 背景说明: 以ACID为特征的事务是关系数据库的一项重要的也是基本的功能。
1629 0
下一篇
无影云桌面