开着飞机换引擎:工行 DBA 专家是如何解决数据库一致性校验的

作者简介:中国工商银行软件开发中心广州技术部

一、背景

在信创转型的浪潮中,信息系统的整体迁移,尤其是同构异构数据库在不同架构硬件间的迁移,便成为一段时间的重点工作。而数据迁移中,对于数据一致性的对比校验,又属于不可或缺的一环,关系到整个迁移工程是否成功,切流后是否存在隐患的关键。

二、需求场景

做过 DBA,尤其是 MySQL DBA 的同学,一定对 1062 这个错误码记忆深刻。这通常意味着又要检查一遍数据一致性,然后选择是跳过该事务还是干脆直接重建备库,而这两个选择也都有各自的风险和成本。至于说此类错误的频出,可能是管理不规范的企业的权限人员在备库执行了操作,也可能是数据库本身的 BUG 导致,深层次原因暂且不在本文探讨,但由此引出的数据一致性的例行扫描这一需求是切实存在的。

再比如说实际生产上曾发生过由 MySQL Bug #83030 引发的主备库 auto_increment 值不一致,而导致主备切换后因数据库异常发生的业务中断。

该BUG广泛存在于 MySQL 5.7 版本中,直到8.0 版本才被修复,所以企业在未进行数据库升级前仍然要对该类问题进行检查和规避。

同时,该问题影响的其实是元数据而非表数据本身,所以只对数据进行校验可能会遗漏部分不一致项。

另外,如文章开头提到的数据库迁移,在信通院发布的《数据库及应用系统迁移指南(2020 年)》中对迁移原则的总结就提到了“数据完整一致原则”:

数据库和应用系统迁移需要遵循数据完整一致性原则。数据完整一致原则并不是要求源数据库和目标数据库的表结构、表数据一模一样,而是要求目标数据库与源数据库所支撑的业务系统结果一致。不能因为数据库的切换导致数据丢失、混乱、不一致,给用户带来不可估量的损失。

如此来看,一款能用、通用、好用的数据库一致性校验工具就成为日常运维、迁移项目关键流程中所需要的帮手。

三、工具简介

目前针对数据库一致性校验的工具有很多,但均有其局限性,比如 MySQL 用户所熟知的 pt-table-checksumpt-table-sync,就仅适用于 MySQL 主从之间的一致性校验和修复。
PingCap 发布的 sync-diff-inspector,可用于校验 MySQL/TiDB 中的两份数据是否一致,但并不支持在线校验,可在确保无数据写入的情况下使用,或通过配置 range 来指定静态数据校验范围。
近期万里数据库开源的 gt-checksum,也是主打静态数据库校验修复工具,但已经可以支持MySQL 和 Oracle 两种数据库,并且提供了扩展其他类型数据库的可能性。
下面先围绕数据库一致性校验工具所应该关注的要点,结合实际生产中的现状和痛点,来探讨工具应该带来的价值和进化的方向。

四、工具能力分析

作为一款专门应用于数据库之间的数据校验工具,最基本的能力应当包括:

  • 数据结构一致性的校验

  • 数据一致性的校验

  • 数据的校验支持抽样方式

  • 支持丰富的高级对象,如:索引、存储过程、分区等

  • 不一致数据的修订能力

  • 优秀的数据比对效率

除此之外,还有一些关键能力也应当给予考虑,比如:

  • 支持多种数据源类型,以及同个数据源的不同部署架构

  • 可以对库、表、列各粒度进行指定或过滤

  • 尽可能低的影响操作环境,不论是负载占用还是锁的持有

  • 权限控制严格的环境下,确保操作安全和数据安全

五、工具流程分析

下面通过对 gt-checksum 项目的学习,结合数据库原理相关知识,简单整理下校验工具的核心功能流程,并以此为基础分析进一步拓展工具能力的可能性。

一致性校验的基本流程如下:

  1. 读取配置主要获取源、目标数据库连接信息,校验对象和方式等配置信息,同时还包括其它高级配置;

  2. 检查用户权限:由于需要连接到数据库执行SQL命令,需要检查对包括元数据(一般是系统视图)和主数据的读权限,如果要进行数据原地修复,还应当包括写权限;
  3. 筛选待校验库表:目前的工具基本是围绕schema、table的匹配和忽略等模式,并支持通配符等方式来进行定义。针对于表级别以下的粒度,比如指定或排除列、指定校验范围(where条件等方式),也是可以考虑实现的需求;
  4. 处理不同数据库对象:这里主要采集包括结构、索引、分区、约束、存错过程、函数、触发器等一系列高级对象并进行比对,绝大部分的采集都是通过查询系统视图,在涉及到异构数据库之间的比对时,有可能需要进行额外处理以避免误报;
  5. 处理表数据:这是校验工作的重头戏,也是耗时相对较多的部分,后面重点分析;
  6. 输出结果:用来指示差异项,并给出人工确认手段和修复语句,当然可执行的修复语句最好是幂等性的,同时不会造成新的差异项。

对于表数据的一致性校验,大致流程如下:

  1. 处理列名:也就是先校验表结构,如果涉及到异构数据库,由于字段类型名称的差异,需要考虑是否严格校验字段类型等存在兼容性问题的属性;

  2. 检查用户的表权限:需要对表有访问权限,如需要原地修复数据则需要修改权限;

  3. 获取全部列信息&获取索引信息:因为配置信息中仅提供到表名级别的信息,关于索引、列的信息均需要通过元数据获取,并且根据规则进行选用,以达到对指定表合理分块和高效查询的目的;

  4. 生成执行计划:根据配置的块大小和前一步选用的索引,逐表逐块生成对应的查询语句;

  5. 执行并校验数据:在源端和目标端分别执行相同的SQL语句,获取结果并进行一致性校验。

以上步骤看似简单,但每一步其实都有大量工作要处理,比如分块键的选择,因为分块校验是必须的,一是保证资源不会被单次大表查询耗尽导致失败,二也是为了降低对目标环境的影响。如果是单列整型的主键则是最理想的情况,如果是联合主键或者表本身没有主键而只有索引,还要考虑索引的类型,是否唯一,是否非空,这些都要充分考虑以确保分块校验的准确性。另外对于是否支持无索引表的一致性校验,笔者认为优先级是最低的,首先无索引表通常为日志表,在迁移或副本同步时的数据保障级别不高;其次,对于无索引表的校验开销是很高的,意义不大。

下方展示了工具针对数据校验的处理过程,和结果的打印。但实际执行的体验上,需要完整处理待校验表list的全量元数据信息,然后依次逐表进行比对校验。在获取元数据的效率,内存使用控制以及go语言本身并行能力上仍有较大的改进空间,

六、功能拓展

由于各种数据库以及其自身功能的丰富度和复杂性,在异构数据库间原本就存在众多兼容性问题的前提下,如何平衡一致性校验的准确度和必要性也成为一款通用工具要考虑的问题。

不过对于实际生产或迁移工程遇到较多的问题,比如支持字符集间的差异、支持源端和目标端存在拓扑架构的差异(比如目标端为分库分表等)、支持分块的动态调整以及在安全的前提下增加并发以提高比对效率等能力,是有必要予以考虑的。

本文来自中国工商银行投稿,作者:中国工商银行软件开发中心广州技术部。

如何优雅转型,做到咖啡运维?XOps 了解一下啊~

6月29-6月30,DOIS DevOps 国际峰会 2023 · 北京站,BizDevOps、精益/敏捷、SRE 稳定性、AIOps,你想看的内容,都在这里!

下滑查看更多👇🏻👇🏻

近期好文:

拼多多研发员工人均薪酬100万;GPT-4被“开源”;AI或取代7800个IBM岗位;75岁图灵奖得主离职谷歌 |一周IT资讯

“高效运维”公众号诚邀广大技术人员投稿

投稿邮箱:jiachen@greatops.net,或添加联系人微信:greatops1118。
点个“在看”,一年不宕机

标签

发表评论