pg_basebackup热备如何保证数据一致性

举报
PostgreSQL 发表于 2019/09/05 15:31:46 2019/09/05
【摘要】 所谓热备就是在数据库不停机的情况下对数据做备份,不影响数据业务,在备份过程中数据不断的改变,PG是如何保证即使数据改变了也能不影响备份呢,这里WAL LOG起了很重要的作用,使用一份基础数据加上一些增量数据能实现这个过程。PG的备份使用了基础文件加上WAL LOG来保证数据的一致性,基础文件是写入到磁盘的已经固化下来的数据,这通过在备份前做一次checkpoint来保证内存中的脏数据全部刷新...

所谓热备就是在数据库不停机的情况下对数据做备份,不影响数据业务,在备份过程中数据不断的改变,PG是如何保证即使数据改变了也能不影响备份呢,这里WAL LOG起了很重要的作用,使用一份基础数据加上一些增量数据能实现这个过程。

PG的备份使用了基础文件加上WAL LOG来保证数据的一致性,基础文件是写入到磁盘的已经固化下来的数据,这通过在备份前做一次checkpoint来保证内存中的脏数据全部刷新到磁盘中,而WAL LOG保存的是在备份过程中改变的数据,这样,利用基础文件+WAL 日志可以将数据库推到一个数据一致的时间点。

                                              image.png

1、 开始备份,设置force_page_writes=true

2、 做一次checkpoint将脏数据刷新到磁盘

3、 开始拷贝数据,同时开始用流复制的方式复制备份过程中产生的WAL日志

以上基础文件+WAL文件看似完美,但实际上不是这样的,因为操作系统不能保证PG的数据页完整的写入到磁盘中。

PG服务器上,内存中的脏页是持续的写入到磁盘中的,写入过程中一般是以页为单位来操作,如果在内存数据刷盘得时候正好去拷贝数据,很有可能拷贝到半页数据,PG默认每个page的大小为8K,一般情况下,PG数据页是以page为单位写入的,但在断电,操作系统崩溃或者热操作(热备)时,极有可能导致部分数据快只写到4K(操作系统一般是以4K为单位写磁盘),这些部分写的页面包含新旧数据的混合,在崩溃后的恢复期间,由于页已经是损坏的页,无法恢复,而在WAL日志里面存储的记录变化信息不够完整,也无法恢复该页,导致数据库启动失败。

image.png

1、 用户DML操作,比如update数据

2、 数据从磁盘读入到内存,并在内存中做了修改,产生脏数据

3、 内存中脏数据刷新到磁盘文件,同时,用户备份操作开始拷贝数据

4、 由于写文件(刷盘)和读文件(拷贝)同时进行,导致拷贝的文件出现半页写的不完整数据。


 

PGforce_page_write解决这个问题,它的原理是在checkpoint之后对所有数据页面的第一次写的时候将整个数据页同时写入到xlog中。

image.png

备注:设置full_page_writes=on后,checkpoint后对每个页中数据的第一次修改都会将整个页全部保存到WAL日志中,如果修改的数据比较零散,可能导致WAL日志大量增加,给系统磁盘带来很大压力。

在没有半页写的情况下,WAL日志中保存的整页数据是没用的,不会覆盖到数据文件中,例如:

image.png

1、 开始恢复

2、 Checksum检查数据页,没有发现半写情况

3、 使用WAL日志恢复备份过程中产生的增量数据

4、 恢复完成

异常出现后,redo操作时通过checksum发现半写的数据页,并将xlog中保存的完整页覆盖当前损坏的数据页,然后再继续做redo,就可以恢复整个数据库。

image.png

1、 开始恢复

2、 Checksum检查数据页,发现有半页写的坏数据

3、 使用WAL中保存的整页数据来修复半页写数据页

4、 WAL日志恢复半页写坏数据

5、 使用WAL日志恢复备份过程中产生的增量数据

6、 恢复完成

Pg_basebackup过程中应用了full_page_write这项技术,在主要流程中,开始调用了do_pg_start_backup()函数,接着开始拷贝数据,在结束的时候调用了do_pg_stop_backup()函数do_pg_start_backup()函数首先设置了full_page_write=on(对应的参数是XlogCtrl->Insert.forcePageWrites= true)然后做了一次checkpoint

image.png

do_pg_stop_backup()函数是对do_pg_start_backup()函数修改过的一些参数做恢复操作,也就是说在备份过程中保持full_page_write=on

image.png

因为full_page_write需要在xlog中记录数据页,会写更多xlog文件,不仅有数据变化信息,还有数据页本身信息,这样会增加额外的IO和磁盘消耗,把full_page_write这个选项关闭会提高数据库执行速度以及减少xlog数量,但是可能导致系统崩溃或者掉电之后的数据库损坏。 如果有减小部分页面写入风险的硬件支持(比如电池供电的磁盘控制器), 或者文件系统支持(能够保证page写入原子性),可以把风险降低到一个可以接受的范围, 那么可以考虑关闭这个选项,其他情况下建议打开这个选择。


【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。