PostgreSQL WAL解析与闪回的一些想法

本文涉及的产品
云原生数据库 PolarDB MySQL 版,Serverless 5000PCU 100GB
简介: 最近在walminer基础做了不少修改,以支持我们的使用场景。详细参考 如何在PostgreSQL故障切换后找回丢失的数据 修改也花了不少精力和时间,这个过程中有些东西想记录下来,方便以后查阅。

PostgreSQL WAL解析与闪回的一些想法

1. 背景

最近在walminer基础做了不少修改,以支持我们的使用场景。详细参考

修改也花了不少精力和时间,这个过程中有些东西想记录下来,方便以后查阅。

所以,这篇东西有点像流水账。

2. WAL文件格式

解析WAL的第一步是要了解WAL的文件格式,我觉得最详细易懂最值得看的资料是下面这个。

但是,以上还不够。细节的东西还是要看源码。我主要看的是写WAL记录的地方。

walminer作者李传成的博客里也有不少WAL解析相关的文章,是后来才发现的,我还没有看过。

3. walminer的解析流程

walminer解析WAL的入口是pg_minerXlog()函数。其主要过程如下

  1. 加载数据字典
  2. 起点搜索解析阶段

    遍历WAL,根据输入的起始时间和起始xid找到匹配的第一个事务。
    这个阶段只解析事务类型的WAL记录,其他WAL记录快速跳过。
  3. 完全解析阶段

    紧接着2的位置,继续往下进行完整的解析。
    这个阶段,会收集所有FPI(FULL PAGE IMAGE)并反映它们的变更,
    还会收集所有DML(insert/update/delete)类型的WAL记录,
    并且在遇到事务提交WAL时输出该事务对应的DML,事务回滚时清空该事务对应的DML。
    

walminer把WAL记录中tuple变成SQL的过程比较有意思,中间用了一个VALUES的临时格式。

以下面这个UPDATE语句为例

update tb1 set c1='3xy' where id=3;

其解析过程中涉及到的一些调用点如下:

pg_minerXlog()
 ->sqlParser()
  ->XLogMinerRecord()
   ->XLogMinerRecord_heap()
    ->minerHeapUpdate(XLogReaderState *record, XLogMinerSQL *sql_simple, uint8 info)
     1. 获取更新前后的tuple值(字符串格式)
     ->getTupleInfoByRecord()
      ->getTupleData_Update()
       ->mentalTup()
        ->mentalTup_nulldata()
        ->mentalTup_valuedata()
         tupleInfo:VALUES(-3, '3x')"
         tupleInfo_old:VALUES(3, NULL)
        
     2. 生成中间redo SQL
     ->getUpdateSQL(sql_simple, tupleInfo, tupleInfo_old,...)
       sql_simple:UPDATE \"public\".\"tb1\" SET VALUES(3, '3xy') WHERE VALUES(3, '3x')
       
     3. 生成中间undo SQL
     ->getUpdateSQL(&srctl.sql_undo, tupleInfo_old, tupleInfo,...)
       srctl.sql_undo:UPDATE \"public\".\"tb1\" SET VALUES(3, '3x') WHERE VALUES(-3, '3xy')"

     4. 生成最终undo SQL
     将中间中" VALUES"之后部分抹去,从rrctl.values,rrctl.nulls,rrctl.values_old,rrctl.nulls_old重新生成SQL后半部分。
     ->reAssembleUpdateSql(&srctl.sql_undo,true);
       srctl.sql_undo:UPDATE "public"."tb1" SET "c1" = '3x' WHERE "id"=3 AND "c1"='3xy' AND ctid = '(0,10)';
      
   
pg_minerXlog()
 ->sqlParser()
  ->parserUpdateSql()
   4. 生成最终redo SQL
   ->reAssembleUpdateSql(sql_ori, false)
   sql_ori:UPDATE "public"."tb1" SET "c1" = '3xy' WHERE "id"=3 AND "c1"='3x';

4. walminer存在的问题

walminer是个非常棒的工具,填补了PG的一个空白。
但是,在我们准备把它推向生产时发现了不少问题。

  1. 资源消耗和解析速度

    • 粗测了一下,解析一个16MB的WAL文件大概需要15秒。不得不说实在太慢了。
    • 解析大量WAL文件还容易把内存撑爆。
  2. 正确性和可靠性

    • 对并发事务产生的WAL记录,解析的结果不对。
    • 缺少回归测试集
    • 其他的小问题。
  3. 易用性

    • 不支持基于LSN位置的过滤
    • 解析一次WAL要调用好几个函数,我觉得没有必要,一个就够了。

对这些已知的问题,都进行了改进。主要有下面几点

  1. 使用单个wal2sql()函数执行WAL解析任务
  2. 支持指定起始和结束LSN位置过滤事务
  3. 支持从WAL记录的old tuple或old key tuple中解析old元组构造where条件
  4. 增加lsn和commit_end_lsn结果输出字段
  5. 添加FPI(FULL PAGE IMAGE)解析开关,默认关闭image解析
  6. 优化WAL解析速度,大约提升10倍
  7. 给定LSN起始位置后,支持根据WAL文件名筛选,避免大量冗余的文件读取。
  8. 修复多个解析BUG
  9. 增加回归测试集
    10.合并PG10/11/12支持到一个分支

修改后的walminer参考

https://gitee.com/skykiker/XLogMiner

后续希望这些修改能合到源库里。

5. 后续改进思路

walminer在功能和使用场景上和MySQL的binlog2sql是非常接近的。

binlog2sql对自己的场景描述如下:

https://github.com/danfengcao/binlog2sql

  • 数据快速回滚(闪回)
  • 主从切换后新master丢数据的修复
  • 从binlog生成标准SQL,带来的衍生功能

binlog2sql已经有很多生产部署的案例,但是walminer好像还没有。
其中原因,我想除了修改版已经解决的那些问题,walminer作为闪回工具,还有进一步改进的空间。

我考虑主要有以下几点可以改进的

  1. 以fdw的形式提供接口
    和函数相比fdw的好处是明显的

    • 不需要等所有WAL都解析完了再输出,因此可以结合limit进行多次快速探测
    • 不需要创建临时表,解析过程中不需要产生WAL(产生WAL可能会触发WAL清理)。
    • 可以在备库执行
      使用fdw后,过滤条件直接通过where条件传递,接口更清晰。无法通过where条件传递东西,比如WAL存储目录,可以通过设置参数解决。
  2. 把解析过程分成事务匹配探测和完全解析2个部分
    完全解析时,需要从匹配的事务往前回溯一部分,确保该事务的SQL甚至所需FPI都被解析到。
    单纯从匹配的事务后面开始完全解析,会丢失SQL的。
  3. 增加DDL解析
    其实并不需要解析出完整的DDL和逆向的闪回DDL,这个任务也很难实现。
    只需要能知道什么时间,在WAL的哪个位点,哪个表发生了定义变更即可。
  4. 代码重构
    从性能和可维护性考虑,有必要进行代码重构。
  5. 工具命名
    既然这个工具的功能是从WAL中解析出原始SQL和undo SQL,walminer这个名称就显得不合适了。
    因为从字面上理解,walminer应该是解析WAL本身包含的信息,包括很多与SQL无关的的信息,
    但是不应该包含undo SQL这种WAL里没有而完全是被构造出来的东西。
    所以,顾名思议,这个东西可以叫wal2sql。

6. 参考

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
相关文章
|
4月前
|
存储 关系型数据库 数据库
postgresql|数据库|提升查询性能的物化视图解析
postgresql|数据库|提升查询性能的物化视图解析
156 0
|
4月前
|
存储 Oracle 关系型数据库
postgresql数据库|wal日志的开启以及如何管理
postgresql数据库|wal日志的开启以及如何管理
276 0
|
2月前
|
关系型数据库 MySQL 分布式数据库
PolarDB for MySQL数据库外网连接解析失败的原因
【2月更文挑战第5天】PolarDB for MySQL数据库外网连接解析失败的原因
63 8
|
3月前
|
关系型数据库 MySQL 分布式数据库
PolarDB for MySQL数据库外网连接解析失败的原因可能有以下几点
【1月更文挑战第21天】【1月更文挑战第105篇】PolarDB for MySQL数据库外网连接解析失败的原因可能有以下几点
45 1
|
8月前
|
数据采集 Cloud Native 关系型数据库
实现业务零停机!NineData的PostgreSQL数据迁移能力解析
NineData推出了PostgreSQL业务不停服数据迁移能力。NineData实现了完全自动化的结构迁移和全量数据迁移,并提供了变更数据的迁移能力。这种能力可以实时监听源PostgreSQL中的变更数据,在完成全量迁移后将变更数据实时复制到目标PostgreSQL,实现源/目标PostgreSQL的动态复制。在PostgreSQL数据迁移过程中,业务可以正常提供服务,无需停服。最终,业务可以根据需求选择对应的时间点切换到目标PostgreSQL。
550 1
|
4月前
|
SQL 关系型数据库 分布式数据库
深度解析PolarDB数据库并行查询技术
深度解析PolarDB数据库并行查询技术:加速SQL执行的关键问题和核心技术 随着数据规模的不断扩大,用户SQL的执行时间越来越长,这不仅对数据库的优化能力提出更高的要求,并且对数据库的执行模式也提出了新的挑战。为了解决这个问题,许多数据库系统,包括Oracle、SQL Server等,都开始提供并行查询引擎的支持,以充分利用系统资源,达到加速SQL执行的效果。本文将深入探讨基于代价进行并行优化、并行执行的云数据库的并行查询引擎的关键问题和核心技术。
123 2
|
4月前
|
SQL 关系型数据库 数据库
postgresql|数据库|pg数据库的文件系统详解---最全面的解析
postgresql|数据库|pg数据库的文件系统详解---最全面的解析
124 0
|
4月前
|
关系型数据库
电子好书发您分享《阿里云认证的解析与实战-关系型数据库ACP认证》
电子好书发您分享《阿里云认证的解析与实战-关系型数据库ACP认证》
44 1
|
6月前
|
前端开发 关系型数据库 Go
《PostgreSQL事务管理深入解析》
《PostgreSQL事务管理深入解析》
70 0
|
6月前
|
关系型数据库 数据库 PostgreSQL
PostgreSQL 的事务管理和并发控制机制解析
PostgreSQL 的事务管理和并发控制机制解析
144 0

推荐镜像

更多