作者:张学程
本文为 DM 源码阅读系列文章的第九篇,在 上篇文章 中我们详细介绍了 DM 对 online schema change 方案的同步支持,对 online schema change 同步方案以及实现细节等逻辑进行了分析。
在本篇文章中,我们将对 shard DDL 同步机制以及 checkpoint 机制等进行详细的介绍,内容包括 shard group 的定义、shard DDL 的同步协调处理流程、checkpoint 机制以及与之相关的 safe mode 机制。
DM 中通过 库表路由与列值转换 功能,实现了对分库分表合并场景下 DML 的同步支持。但当需要同步的各分表存在 DDL 变更时,还需要对 DDL 的同步进行更多额外的处理。有关分表合并时 shard DDL 同步需要处理的问题以及 DM 中的同步支持原理,请先阅读 TiDB Ecosystem Tools 原理解读系列(三)TiDB-DM 架构设计与实现原理。
在 这篇文章 中,我们介绍了 DM 在处理 shard DDL 同步时引入了两级 shard group 的概念,即用于执行分表合并同步任务的各 DM-worker 组成的 shard group、每个 DM-worker 内需要进行合表同步的各上游分表组成的 shard group。
DM-worker 组成的 shard group
由 DM-worker 组成的 shard group 是由集群部署拓扑及同步任务配置决定的,即任务配置文件中定义的需要进行合表同步的所有上游 MySQL 实例对应的所有 DM-worker 实例即组成了一个 shard group。为了表示同步过程中的相关动态信息,DM-master 内部引入了两个概念:
Lock 中各主要成员变量的作用如下:

DM-worker 内分表组成的 shard group
每个 DM-worker 内的 shard group 是由对应上游 MySQL 实例内分表及同步任务配置决定的,即任务配置文件中定义的对应 MySQL 实例内需要进行合并同步到同一个下游目标表的所有分表组成一个 shard group。在 DM-worker 内部,我们维护了下面两个对象:
ShardingGroup 中各主要成员变量的作用如下:
对于两级 shard group,DM 内部在依次完成两个级别的 相应的 shard DDL 同步协调。
DM-worker 间 shard DDL 协调流程
我们基于在 这篇文章 中展示过的仅包含两个 DM-worker 的 shard DDL 协调流程示例(如下图)来了解 DM 内部的具体实现。

DM-worker 内 shard DDL 同步流程
我们基于在 实现原理文章 中展示过的一个 DM-worker 内仅包含两个分表 (table_1,table_2) 的 shard DDL(仅一条 DDL)协调处理流程示例来了解 DM 内部的具体实现。
table_1 的 DDLtable_1 的 DML 并同步 table_2 的 DMLtable_2 的 DDL(流程与 step.1 一致)table_1 在 step.3 时忽略的 DML,解析后向下游同步需要注意的是,在上述 step.1 与 step.4 之间,如果有收到 table_1 的其他 DDL,则对于该 shard group,需要协调同步由一组 shard DDL 组成的 ShardingSequence。当在 step.9 对其中某一条 shard DDL 同步完成后,如果有更多的未同步的 shard DDL 需要协调处理,则会重定向到待处理的下一条 shard DDL 对应的位置重新开始解析 binlog event。
DM 中通过 checkpoint 机制来实现同步任务中断后恢复时的续传功能。对于 load 阶段,其 checkpoint 机制的实现在 DM 源码阅读系列文章(四)dump/load 全量同步的实现 文章中我们已经进行了介绍,本文不再赘述。在本文中,我们将介绍 binlog replication 增量同步阶段的 checkpoint 机制的实现及与之相关的 safe mode 机制的实现。
DM 在 binlog replication 阶段以 binlog event 对应的 position 为 checkpoint,包括两类:
DM 的 checkpoint 信息保存在下游数据库中,通过 RemoteCheckPoint 对象进行读写,其主要成员变量包括:
globalPoint:用于保存全局 checkpointpoints:用于保存各 table 的 checkpointcheckpoint 信息在下游数据库中对应的 schema 通过 createTable 方法进行创建,其中各主要字段的含义为:

对于全局 checkpoint,在以下情况下会更新内存中的信息:
对于各 table checkpoint,在以下情况下会更新内存中的信息:
对于全局与 table 的 checkpoint,会在以下情况下 flush 到下游数据库中:
值得注意的是,在 shard DDL 未同步到下游之前,为确保中断恢复后仍能继续整个 shard DDL 的协调过程,DM 不会将全局 checkpoint 更新为比 shard DDL 起始 position 更大的 position,DM 也不会将 shard DDL 协调过程中对应 table 的 checkpoint flush 到下游。
当同步任务中断恢复后,DM 在 binlog replication 阶段通过 checkpoint 机制保证了重新开始同步的起始点前的数据都已经成功同步到了下游数据库中,即保证了 at-least-once 语义。但由于 flush checkpoint 与同步 DDL、DML 到下游不是在同一个事务中完成的,因此从 checkpoint 开始重新同步时,可能存在部分数据被重复同步的可能,即不能保证 at-most-once 。
在 DM 的 binlog replication 阶段,通过增加 safe mode 机制确保了重复同步数据时的可重入,即:
://github.com/pingcap/dm/blob/369933f31b/syncer/dml.go#L132">将 INSERT 操作转为 REPLACE 操作://github.com/pingcap/dm/blob/369933f31b/syncer/dml.go#L195">将 UPDATE 操作转为 DELETE 操作和 ="https://github.com/pingcap/dm/blob/369933f31b/syncer/dml.go#L200">REPLACE 操作
ub.com/pingcap/dm/blob/369933f31b/syncer/dml.go#L265">对 DELETE 操作不进行转换仍保持为 DELETE目前,safe mode 会在以下情况时启用:
本篇文章详细地介绍了 shard DDL 机制与 checkpoint 机制的实现,内容包括了两级 shard group 的定义与 DM-worker 间及 DM-worker 内的 shard DDL 同步协调处理流程、checkpoint 机制及与之相关的 safe mode 机制。下一篇文章中,我们将介绍用于保证 DM 正确性与稳定性的测试框架的实现,敬请期待。
原文阅读:https://www.pingcap.com/blog-cn/dm-source-code-reading-9/
更多 DM 源码阅读:
博客 | PingCAP
原文作者:;如有侵权,请联系管理员删除。