本文为 TiDB Data Migration 源码阅读系列文章的第四篇, 《DM 源码阅读系列文章(三)数据同步处理单元介绍》 介绍了数据同步处理单元实现的功能,数据同步流程的运行逻辑以及数据同步处理单元的 interface 设计。本篇文章在此基础上展开,详细介绍 dump 和 load 两个数据同步处理单元的设计实现,重点关注数据同步处理单元 interface 的实现,数据导入并发模型的设计,以及导入任务在暂停或出现异常后如何恢复。
dump 处理单元
dump 处理单元的代码位于 github.com/pingcap/dm/mydumper 包内,作用是从上游 MySQL 将表结构和数据导出到逻辑 SQL 文件,由于该处理单元总是运行在任务的第一个阶段(full 模式和 all 模式),该处理单元每次运行不依赖于其他处理单元的处理结果。另一方面,如果在 dump 运行过程中被强制终止(例如在 dmctl 中执行 pause-task 或者 stop-task),也不会记录已经 dump 数据的 checkpoint 等信息。不记录 checkpoint 是因为每次运行 Mydumper 从上游导出数据,上游的数据都可能发生变更,为了能得到一致的数据和 metadata 信息,每次恢复任务或重新运行任务时该处理单元会 清理旧的数据目录 ,重新开始一次完整的数据 dump。
导出表结构和数据的逻辑并不是在 DM 内部直接实现,而是 通过 os/exec包调用外部 mydumper 二进制文件 来完成。在 Mydumper 内部,我们需要关注以下几个问题:
-
数据导出时的并发模型是如何实现的。
-
no-locks, lock-all-tables, less-locking 等参数有怎样的功能。
-
库表黑白名单的实现方式。
Mydumper 的实现细节
Mydumper 的一次完整的运行流程从主线程开始,主线程按照以下步骤执行:
-
解析参数。
-
会根据
no-locks
选项进行一系列的备份安全策略,包括 long query guard和 lock all tables or FLUSH TABLES WITH READ LOCK。