PostgreSQL码农集散地

为什么FPW是以牺牲(性能、存储空间、稳定性)换取的可靠性?

文章开始前推荐2个学习环境: 

1、欢迎使用镜像快速体验PostgreSQL/DuckDB强大功能:《最好的PostgreSQL学习镜像》

2、欢迎使用云起实验室: 《免费体验PolarDB开源数据库》

3、PolarDB开源数据库内核、应用等学习图谱:  https://www.aliyun.com/database/openpolardb/activity 

为什么FPW是以牺牲(性能、存储空间、稳定性)换取的可靠性?

https://www.bilibili.com/video/BV1jR4y137Yo/

背景知识:
数据库的数据文件以block的形式来进行组织. 每个block的大小可选2k,4k,8k,16k,32k.
修改数据块的内容时, 先将数据块从存储读到shared buffer里, 修改后再由bgwriter或checkpointer调度从shared buffer内存写入到磁盘.
磁盘通常以扇区(512字节)进行组织, 一次IO的最小单位也通常小于block size, 那么当block正在从内存写入到磁盘时, 如果发生这几个事情, 可能出现坏块:

  • 断电, block的一部分可能是新的状态, 另一部分可能是老的状态.

  • 在线备份, 拷贝文件, 同样拷贝到的block的一部分可能是新的状态, 另一部分可能是老的状态.

  • 磁盘快照, 快照内的block的一部分可能是新的状态, 另一部分可能是老的状态.

如果出现坏块, 将导致数据不一致或损坏. 怎么检测出这种块错误?

  • block checksum.

怎么解决坏块问题?

  • FPW, full page write. 在将block从内存写出到磁盘前, 必须确保这个block的完整页面的内容已经写入到wal日志中(对于同一个block, 每次checkpoint后只有这个block第一次发生变化时需要写一次full page到wal中).

    • 如果开启了FPW, 即使出现了datablock 坏块, 也能从wal的full page中恢复到一致的状态.

fpw 牺牲了什么?

  • 性能:

    • 当更新或删除时, 每次checkpoint后都要写入更多的wal(fpw), 即使每个page只更新1条记录, 第一次也需要写1个完整的page. 导致性能损耗. 如果checkpoint频繁, 这个性能损耗会更加明显.

    • 当datablock被vacuum进行垃圾回收或freeze时, 每次checkpoint后第一次修改的page需要写完整的page到wal(即使每个page只更新少量内容). 导致性能损耗. 如果checkpoint频繁, 这个性能损耗会更加明显.

  • 存储空间:

    • 消耗更多的WAL存储空间: 包括wal目录, 归档文件, standby的wal文件.

    • 同时消耗更多网络带宽(primary-standby的网络带宽)

  • 稳定性(指SQL RT)

    • 对于高并发频繁update, delete的场景, 每次checkpoint时, SQL RT 抖动会比较明显, 原因: 此时WAL日志暴增(full page write), wal的排他锁、IO写延迟等可能更加集中. 影响性能.

PolarDB:

  • PolarDB 计算存储分离架构版本. 采用PolarStore, 支持大于block size的原子写.

    • 因此不需要开启fpw.

  • PolarDB 三节点分支, 同样允许关闭fpw. 关闭fpw后采用从standby节点读取datafile来解决FPW的问题. 详见:

    • 《PolarDB PostgreSQL 开源训练营回放》

本期问题1:
请问PolarDB PG三节点版本在关闭fpw后进行数据恢复时, 从哪里读取checksum有错误的data block?

  • a. WAL里面的full page datablock

  • b. 当前实例的数据文件

  • c. standby节点的数据文件

  • d. 归档的WAL日志文件

答案:

  • c

解释:

  • PolarDB PG三节点版本可以关闭fpw, 关闭fpw后, 会从standby节点的数据文件读取需要的data block.

本期问题2:
请问PolarDB PG共享存储版本为什么可以关闭fpw而不会导致data block出现partial write的坏块?

  • a. 存储支持超过data blocksize的原子写.

  • b. 开启了 block checksum

  • c. 在其他地方写了一份FULL PAGE

  • d. 从standby 节点取得full page

答案:

  • a

解释:

  • PolarDB 计算存储分离版本采用PolarStore存储或者其他支持超过data blocksize的原子写的SAN存储或者分布式块存储时, 存储的原子操作和PFS对齐后, 可以关闭fpw, 而不会产生data block的partial write.

本期问题3:
请问开启full page write有哪些负面影响?

  • a. recovery时需要从wal中读取full page导致恢复性能下降.

  • b. 高并发的更新、删除小事务, 在遇到检查点时很大概率会发生较为明显的SQL RT抖动

  • c. 在发生vacuum freeze时, 由于开启fpw可能产生大量的full page, 导致standby延迟变大

  • d. 如果检查点频率很高, 开启fpw会导致写更多的wal日志, 从而导致归档的拷贝压力、存储空间变大

答案:

  • bcd

解释:

  • fpw不影响恢复性能, 反而可能对恢复性能有帮助, 因为不需要从datafile中获得block(减少了离散IO).

本期问题4:
请问以下哪些文件系统可以关闭full page write而不会导致数据文件不一致的问题?

  • a. zfs

  • b. ext4

  • c. xfs

  • d. 支持cow(copy on write)功能的文件系统

答案:

  • ad

解释:

  • 文件系统支持copy on write, 并且在打开cow后, 实际上与数据库FPW的功能类似, 因此可以关闭数据库的fpw.

欢迎关注我的github (https://github.com/digoal/blog) , 学习数据库不迷路.  

近期正在写公开课材料, 未来将通过视频号推出, 欢迎关注视频号:

Image

文章中的参考文档请点击阅读原文获得.