解锁 DM 数据迁移旅程分库分表协调难题

网友投稿 204 2024-04-27



一、概述

介绍了与悲观协调有关的各个数据结构之后,接下来将介绍一个 DM 系统从接受到第一条分表 DDL 开始,到所有该 DDL 对应的 Lock resolved 的全过程。

解锁 DM 数据迁移旅程分库分表协调难题

本节内容皆参考 DM v6.0,对现在而言,有可能已过时,欢迎大家提出意见~

二、Overview

假设现在起了 master 和两个 Worker,两个 Worker 分别绑定两个 Source(s1,s2),每个 Source 有两个分表(t1,t2),这四个表会 route 到一个 target table(tarTbl)中。在 DDL 到来之前,两个 worker 会创建好 ShardingGroupKeeper,里面只有一个 target table,两个 source table。

两个 Worker 先后收到两个 Source 四个分表的同一条 DDL,表示为:

DDL1:表示对 s1.t1 的 DDL。

DDL2:表示对 s2.t1 的 DDL。

DDL3:表示对 s1.t2 的 DDL。

DDL4:表示对 s2.t2 的 DDL。

三、具体过程

本小节 worker 对 DDL 的处理从 handleQueryEventPessimistic

接下来将对上图中的步骤一一介绍

Step 1

worker1 收到来自 source1 的 DDL1,会直接TrySync,这里返回了一大堆的参数,其实有用的就只是 synced,简单来说,里面只做了一件事:AddItem。下面详细介绍一下 TrySync

本节,假设该 DDL 不是 CreateTableStmt,如果是的话,也很简单,每次都是 remain <=0,synced = true,但是只有第一次发送该 create table 的 worker 会 syncDDL。

TrySync

想要知道 worker 在悲观协调的时候做了什么,必须要搞懂 TrySync 是怎么运作的。在此之前,我们来重新理解一下 ShardingGroupKeeper:

单独拿出一个 ShardingGroup 举例(颜色代表 DDL 的种类):

Example

worker 收到了以下 DDL

依次收到了 table1 橙色、黄色、绿色三条 DDL

收到了 table2 橙色

这个时候 activeIdx = 0remain = 1,因为只有 table3 没有收到 active DDL 了

如果在这个时候收到了 table3 橙色 DDL,remain = 0,处理了这条 DDL 之后,active ++

如果这个时候收到 table2 绿色 DDL,则会报错,悲观协调要求同一个 source table 中 DDL 必须有序

如果 group 中所有的 DDL 都 resolved 了。则会重置一下 meta

总结:AddItem 就是上面图中把 DDLItem 放进 ShardingSequence 的过程

Step 2 与 Step 1 相同

Step 3

由于 tarTbl 只有两个 source table:s1.t1 和 s1.t2,这时 TrySync 后,synced = true,说明该 worker ready

Step 4

worker1

PutInfo:发送 ready info 给 master(后面会详细介绍这个函数)

之后会被阻塞,等待 master 发送 operation

Master

watchInfoPut:成功监听到了

handleInfoPut:master 也开始TrySync,master 的 TrySync 相比 worker 中的要简单很多,每一个 Info 直接相当于该 source/worker 已 ready,所以直接统计是否所有 ready 即可

由于这里是第一个 worker 发 info 给 master,所以需要新建 Lock,新建 Lock 过程中会获取该 task 所有的 source,并存到 lock 中,这样就知道还有多少 source 没 ready。显然还有 source2 没 ready。

继续等待

Step 5 与 Step 3 相同

Step 6

前面与 Step 4 相同,但是这时所有 source 都 ready 了,synced = true

Step 7

master

putOpForOwner:发送 exec operation to owner(worker1)

Worker1

得到 master 的 exec operation

NewDDLJob 并 handle

addJob:发送 job 给 DDLJobCh

syncDDL:之前 worker 起的协程接受到该 job

拿到刚刚得到的 operation,并且不会被跳过,因为 ignore = false

Step 8

同步到下游

Step 9

Worker1

DoneOperationDeleteInfo:发送 done operation 给 master 并删除 info

Step 10

Master

接受 done operation

markDone

putOpsForNonOwner:给其他所有 non-owner 发送 skip info(skip done 是为了防止把 done 覆盖掉)

Worker2

接受到了 no exec(skip) 的 operation,和 Step 7 类似,但是在 syncDDL 的时候会被 skip

Step 11 和 Step 9 相同

四、总结

本节介绍了在悲观协调过程中,遇到第一条 DDL 语句,生成 Lock,到收到所有 DDL 语句,Lock 解除的过程。

经过本节的学习,我

五、疑似 bug

initShardingGroups 中对 ShardingGroup.sources 进行了初始化,这里包含了该 targetTable 对应的所有 sourceTables

TrySync 的时候,却使用第一个 sourceTable[0],来标记所有的 DDL[],如果 len(DDL[]) != 1,则 remain 永远不可能为 0。因为 sourceTables 来源于 ddlInfo。而 DDLInfo 只存了第一条 ddl 的 ddlInfo,实际上对于每一个 Split 之后的 DDL,都会 genDDLInfo

但是奇怪的是,代码中标注了不支持 multi-table DDL,这个 error 在 pessimist/optimist mode 中都用到了。但是在现在看 pessimist 代码中,又看到其为 multi-table DDL 实现了部分相关逻辑。。。有毒

比如:

https://github.com/pingcap/tiflow/blob/release-6.0/dm/syncer/syncer.go#L2957-L2960

https://github.com/pingcap/tiflow/blob/release-6.0/dm/syncer/sharding-meta/shardmeta.go#L35

。。。

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:解决TiDB binlog中drainer异常的周期性故障处理方法
下一篇:记录 TiDB v5.2.3 迁移到 v6.1.0 的升级过程
相关文章