同时也正如很多商业智能应用需要将数据汇总用作分析,这家公司的业务系统也有类似的汇总数据库,这种级联关系会让数据同步操作进一步复杂化。最终该公司使用了UDTS作为跨云数据同步的解决方案,在保障数据一致的同时,DBA只需要提供两边数据库的连接和账号信息即可将数据同步任务托管,释放了运维人员的精力,专注去处理业务上的数据库工作需求。
数据同步
前面提到MySQL事务,在理解存量数据迁移过程中的数据一致性时,需要先了解InnoDB为代表的事务引擎和MyISAM代表的非事务引擎。使用MyISAM引擎的数据表确实没有很好的数据一致性确保手段,存量数据只能对数据表加读锁并迁移,在完成存量数据同步后,通过binlog追平,这样因为读锁会阻塞数据的写入,会导致业务的写入功能不可用,而且这一不可用的时间视表中数据体量而定。
然而因为MyISAM的不灵活,实际互联网公司中已经很少使用MyISAM引擎了。而InnoDB引擎因为它支持事务和行级锁的特性,在数据同步过程中对业务的影响小很多,但也因此对数据一致性的保护方法也相对复杂,而这一套一致性保护方法,核心就在于基于连接session的事务隔离和基于MVCC的数据版本管理,而UDTS也正是基于此而实现数据一致。
数据校验
数据一致性的关键,除了数据同步过程中的一致性保障,更加简单直接的手段是数据校验,只有对比过数据是一致的,那才是真正的一致。MySQL数据校验的手段有很多,其中最经典的是pt-table-checksum。
pt-table-checksum会新建一个临时的checksum表,并且获取与主库有主从关系的所有从库信息。在校验工作时,工具会将该session的binlog格式设置为statement,这样是为了利用mysql的binlog机制,将主库上执行的sql语句同步到从库去。接着工具会以chunk为单位从主库中读取数据和计算校验,将校验结果写入checksum表,这个过程会在一个语句中完成,随后这个语句由于对checksum表进行修改,会被同步到从库并且被从库执行。这样从库也会在自己的checksum表写入校验值。这个时候工具再从库中把checksum值读出,就可以与主库的计算值进行对比。
pt-table-checksum的优势在于使用方便,在经历了多年迭代也有非常好的可靠性保证。但是它的技术限制也是明显,那就是要求被校验的两个库需要是主从关系,同时也要求数据表有索引,因为chunk大小的计算是通过索引完成的。
【案例】
以近期的xx公司迁移到UCloud为例,在数据同步的阶段由于数据库实例众多,需要减少DBA的工作负担而采用了UDTS来进行数据库迁移,但是这样就打破了源和目标库的主从关系,进而导致pt-table-checksum无法使用。当然实际上数据导出-传输-导入-配置主从这样的机械化操作可以通过制作脚本来解决,但是为了迁移而开发一套复用率不高的脚本代码并不明智。这时候sync_diff_inspector工具的优势就体现出来了。
sync_diff_inspector是TiDB团队为了方便用户在MySQL数据迁移到TiDB后对数据一致性进行检查的开源工具,它不要求被校验的两个数据库存在主从关系,也没有对数据表索引的要求,甚至允许源库和目标库有不同的库名和表名,只要有明确的映射,就可以对数据本身进行校验。同时,在sync_diff_inspector发现某一块数据存在差异的时候,会通过二分对比的办法,最终找到实际不一致的行,缩小了疑似不一致的数据范围。
虽然这种相对松耦合的环境下对数据进行校验,可能会出现记录下一些数据不一致,例如主库的某个写入还没有完全即时的同步到从库,这时候进行检查可能会存在数据差异,但是除非源库insert/delete/update操作非常频繁,否则一般期望工具检查发现的差异不会太多。这时候只需要针对检查报告中的少数差异做第二次的手工或脚本校验,就可以确认数据一致性。当然如果一致性检查工具发现有较多数据不一致,一是可以用检查工具生成的一致性修复脚本来修复一致性,也可以对通过对数据进行重新同步来完成。