01概述
AntDB数据库是一款国产自研的MPP架构的分布式数据库,高度兼容Oracle语法,在通信、金融、交通等多个行业应用广泛。用户在使用AntDB数据库的过程中,经常由于误操作、应用程序Bug等,导致了误删数据或者误更新数据,影响业务正常使用。误删数据不是某个数据库的个例,几乎所有的数据库都会遇到类似问题,并且大多数数据库都会提供一个【数据闪回】的工具,利用该工具可以快速恢复误操作数据。
根据误操作类型,可以将数据闪回分为DML数据闪回和DDL数据闪回。DML数据闪回主要针对insert、update、delete场景,DDL数据闪回主要针对drop table、truncate table场景,而AntDB能够支持DML和DDL这两种数据闪回。本文将主要介绍DML数据闪回的实现细节。
02方案选型
AntDB 的DML数据闪回有两种主流的实现方式。第一种是基于WAL日志的数据闪回,它有两个前提条件,表结构未发生改变并且保留足够的WAL日志,结合表结构元数据,解析WAL日志进行数据恢复。第二种基于MVCC机制实现,AntDB更新、删除记录并不是真正的删除,而是生成新的记录,并将旧的记录进行标记,从而在vacuum执行前,能够利用记录的多版本信息以及事务提交信息找回旧的记录。两种方式都有各自的适用场景及弊端。
基于WAL日志的数据闪回需要保留大量的WAL日志文件,这会占用大量存储空间。在WAL文件数量较多时,需要遍历所有WAL日志,耗时较长,并且表不能做DDL操作。它的优点是逻辑简单,在技术实现上较容易,且社区有现成的开源实现可供参考。
而基于MVCC的机制则需要保证vacuum不会清除不用的多版本元组,vacuum相关参数需要谨慎设置。由于多版本元组不能及时清除释放,同样也会带来占用大量空间的问题。但相对来说,基于MVCC的实现方式更复杂,需要更深层地修改内核代码,因此在调研完两种方案的优缺点后,我们选择基于WAL日志的DML数据闪回实现方式。
03实现原理
3.1 WAL日志组成
WAL日志由一个个Record组成,Record分为不同的类型,如图1所示:
AntDB的底层存储是堆表。从数据闪回的角度,只需要关心Heap表以及事务相关的类型,其他的Record类型不影响数据闪回的结果。事务相关的Record记录了事务的状态,commit或者abort,abort状态的事务数据不需要闪回,因此只需要关心commit状态的事务。
Heap类型的Record,记录了insert、update、delete操作产生的事务数据,根据DML类型可以再进行细分,如图2所示:
3.2 解析流程
DML数据闪回支持按表名闪回、按时间区间闪回、按事务号XID闪回、按LSN区间闪回。从内部实现上来看,这些闪回方式最终都会转换为一个LSN区间,包含起始LSN和结束LSN,如果指定了表名,则会在解析WAL Record记录时按表名进行过滤。图3中的 lsn3~lsn4即为解析的LSN区间。
基于WAL日志的数据闪回需要设置两个重要的参数:wal_level和full_page_writes。第一种参数wal_level需要设置为replica或者logical,minimal级别保存的信息较少,不足以恢复数据。第二种参数full_page_writes需要设置为on。AntDB每次 checkpoint 之后page的首次更新,都会将page页面完整地写入到 WAL 日志中。这种机制在宕机等异常场景下能够保证数据不丢失,比如在脏页刷盘时发生崩溃,并且在恢复时发现原始页面损坏,那么这时就可以通过WAL里面的full page进行恢复。Full Page Write(简称FPW)页面保存了页面的原始数据,这对于解析WAL数据至关重要,一些Record记录它本身的数据对于解析出完整的正向SQL和反向SQL并不充分,需要依赖FPW提供的原始数据。FPW在一次checkpoint之后才会写,在闪回数据时,选择的LSN区间应当在一个可用的checkpoint之前。在代码实现上,即使LSN区间在checkpoint之后,也会往前搜索,直到搜索到一个可用的checkpoint。
在确定了WAL的LSN区间后,就可以对此区间内的WAL Record做解析。根据不同的Record类型,结合元数据、FPW,拼接出原始SQL以及闪回SQL,记录到结果表中。整体解析流程如图4所示:
在解析WAL日志的过程中,解析程序以事务作为基本单位进行解析。一个事务对应一个TransactionEntry对象,一个事务可以包含多个SQL语句,每个SQL语句对应change链表的一个元素。在事务提交时,将change链表的所有元素拼接出正向SQL文本,以及反向SQL文本。
3.3 toast表解析
WAL解析过程中的一个难点是toast表。AntDB对于大字段的表,使用toast机制进行存储。toast英文全称为The OverSized Attribute Storage Technique(超尺寸字段存储技术)。toast机制的主要思路是使用额外的toast 表来存储大字段数据,避免一条记录跨越多个page页面,在原始的字段存储区内存储对应的toast 表的oid以及其数据行的chunk_id。
pg_class表的reltoastrelid 字段记录的就是其对应的toast表的oid,toast表的表名后缀为其父表的oid。举例来说,一张普通表 t,oid 为 10022077,reltoastrelid 为 10022080,表t对应的toast表为:pg_toast_10022077,oid 为 10022080。普通表与 toast 表在 pg_class 中通过字段 relkind 进行区分,普通表为 'r',toast 表为 't'。
对一个涉及大字段的普通表执行DML操作,该表与其对应的toast表的wal写入顺序如下:
- insert操作,先插入toast表记录,再对普通表进行写入
- update操作,先插入toast表记录,再删除toast表记录,最后更新普通表
- delete操作,先删除普通表记录,再删除toast表记录
以上可以看出,insert与update都是先对toast表进行操作,然后对普通表操作,而delete则相反,这一点对于处理delete场景下的toast表数据闪回至关重要。
3.4 闪回数据存储
WAL日志解析拼接出来的SQL将会存储在表中,表结构如表1所示:
表1 解析结果表
字段名称 | 字段类型 | 字段描述 | 备注 |
---|---|---|---|
sqlno | int | SQL序号 | SQL在事务中的编号 |
xid | bigint | 事务号 | |
topxid | bigint | 父事务号 | 子事务的父事务号 |
sqlkind | int | SQL类型 | |
minerd | bool | 是否成功解析 | |
timestamp | timestampTz | 事务提交时间 | |
op_text | text | 原始SQL | |
undo_text | text | 闪回SQL | |
complete | bool | 是否已完成 | |
schema | text | schema名称 | |
relation | text | 表名称 | |
start_lsn | pg_lsn | 起始LSN | |
commit_lsn | pg_lsn | 事务提交LSN |
op_text为原始的SQL语句,undo_text为闪回的SQL语句。如果想快速恢复数据,则需要将undo_text导出,按时间逆序执行一次,即可恢复这段时间的数据。
04 使用示例
创建一张表t,插入3条记录,然后再删除表t的所有记录,如图5所示:
执行DML数据闪回函数wal2sql,指定表名t为参数,执行完成后从wal2sql_contents表中能够看到DML数据闪回的结果,op_text表示原始的SQL,undo_text表示反向的闪回SQL,如图6所示:
05 改进与提升
AntDB DML数据闪回工具在开发过程中,解决了一系列涉及具体场景的问题,主要包括toast表解析、子事务解析、Oracle兼容性问题;同时还解决了涉及具体场景的性能问题,如海量表场景下的性能问题、大数据量场景下的性能问题。AntDB DML数据闪回工具不仅支持AntDB单机版本,还支持AntDB分布式集群场景下的数据闪回。
(1)toast表解析问题主要是由于delete场景下原表与toast表在处理顺序上与insert和update不同,此处需要特殊处理,否则会导致toast表在delete场景下解析结果不正确。
(2)子事务是AntDB使用较多的一个场景,子事务的解析需要严格考虑父子事务之间的关系以及事务提交状态,解析子事务时应当保证子事务的准确性,不能出现丢失部分子事务的情况。
(3)Oracle兼容是AntDB的一大特色,AntDB高度兼容Oracle语法和存储类型,比如Oracle类型rowid。数据闪回需要考虑Oracle兼容性,保证在Oracle语法下创建的表以及生成的数据能够正确闪回。
(4)数据闪回需要支持分布式集群,AntDB分布式架构下数据分散存储在不同的数据节点上,DML数据闪回能够支持所有数据节点的数据闪回。在使用方法上只需要连接到任意一个CN节点执行数据闪回命令,与单机版本在使用方法上完全一致,做到了简单易用。
(5)数据闪回的性能提升,主要包括海量表场景下的执行性能提升,比如数据库中包含超过100万张以上的表,元数据数量巨大,此场景要保证解析性能不会出现较大的下降。此外,大事务场景下的执行性能优化,1个事务包含大量SQL以及大字段涉及大量toast表的解析,都需要保证性能不会有太大的损耗。
06总结
本文介绍了AntDB基于WAL日志实现DML数据闪回的一种方式,讨论了其实现原理,并在社区开源实现的基础上做了大量改进和提升。数据闪回是一个非常重要的工具,虽然平时使用频率不高,但在紧急关头能够挽救数据。数据闪回不限于一种方式,AntDB在未来将探索基于MVCC多版本控制的数据闪回,为数据恢复提供更多实现路径。
关于AntDB数据库
AntDB数据库始于2008年,在运营商的核心系统上,为全国24个省份的10亿多用户提供在线服务,具备高性能、弹性扩展、高可靠等产品特性,峰值每秒可处理百万笔电信核心交易,保障系统持续稳定运行近十年,并在通信、金融、交通、能源、物联网等行业成功商用落地。