DM 分库分表 DDL “悲观协调” 模式介绍丨TiDB 工具分享

2024-04-08 02:08

本文主要是介绍DM 分库分表 DDL “悲观协调” 模式介绍丨TiDB 工具分享,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

背景

TiDB 作为分库分表方案的一个 “终结者”,获得了许多用户的青睐。在切换到 TiDB 之后,用户告别了分库分表查询和运维带来的复杂度。但是在从分库分表方案切换到 TiDB 的过程中,这个复杂度转移到了数据迁移流程里。TiDB DM 工具为用户提供了分库分表合并迁移功能,在数据迁移的过程中,支持将分表 DML 事件合并迁移,并一定程度支持上游分表进行 DDL 变更。

本文以及后续文章主要介绍分库分表合并迁移时,各分表 DDL 变更的协调。DM 的分库分表 DDL 协调可配置为 “悲观协调” 和 “乐观协调” ,本文主要介绍 TiDB DM 分库分表 DDL 协调的 “悲观协调” 模式。后续文章会介绍 “乐观协调” 模式。

分库分表 DDL 的问题(简略版)

本节首先以一个例子粗略介绍分库分表 DDL 对数据迁移的影响,然后就这个问题给出更加正式的定义。

假设在两个上游有两个分表 t1、t2,下游表为 t。

t1 接下来的同步事件是 INSERT (3,3),t2 接下来的同步事件是 DROP COLUMN c2。如果 DROP COLUMN c2 先被同步到下游,在同步到 INSERT (3,3) 时就会因为缺少 c2 列而报错。
因此我们要对 DDL 同步事件进行特殊处理。

分库分表合并迁移的定义

接下来我们尝试使用更正式一点的语言来描述这个问题,从而引出如何正确解决这个问题。

从用户的角度来讲,数据库的用途主要的是查询,在分库分表合并前后,查询的结果应该是相同的(不考虑 LIMIT 等算子以及不确定性查询)。也就是说,各分表查询结果的并集应当等于迁移后的查询结果。容易得到一个满足此要求的充分条件:各分表数据的并集应当等于迁移后的表数据。考虑到同步延迟的影响,也就是当前时刻下游表的数据等于各分表在过去某时刻数据的并集。
对于这个定义而言,数据迁移就是让各分表的同步时刻不断向前推进。如果在同步某事件前,下游表与各分表满足定义,那么我们将一个分表的同步事件以相同影响的方式应用到下游,就将该分表的同步时刻正确地推进了。

分库分表 DDL 的问题(正式版)

从上面的定义来看,DDL 会造成两个方面的问题。

首先是 DDL 可能会变更表结构。参照之前的例子,如果 t1、t2 都有 DROP COLUMN c2 事件,DM 先同步到了 t2 的该事件,而同步事件需要以相同影响的方式应用到下游,我们应该只将下游 t2 对应的数据 DROP COLUMN。显然下游 t1、t2 的数据共享一个表结构,无法完成这个操作。因此 t2 的该事件暂时不能被同步。
另一个问题是,部分 DDL 即使不影响表结构,也会产生对数据产生影响。例如 ALTER TABLE DROP COLUMN c, ADD COLUMN c DEFAULT xx,会将一个分表的 c 列全部修改为 xx。目前 DM 的实现同样无法将这个事件以相同影响的方式应用到下游

解决方法

对于上述 DDL 引入的问题并基于前文对于同步正确性的定义,我们可以得到一个满足要求的充分条件:当某分表出现 DDL 同步事件时,我们将其同步暂停;直到所有分表都出现该 DDL 同步事件时,我们将 DDL 应用到下游并恢复所有分表的同步。此时我们可以保证下游表的 DDL 产生的影响等于所有分表都进行了 DDL(不考虑非确定性 DDL,例如 DDL 新增列默认值为 current_timestamp)。

悲观协调例子

我们仍然以两张表 t1、t2 的合并迁移为例,观察 binlog 同步进度

左图中,当分表 t1 遇到 DDL 时,t2 同步事件还没有到这条 DDL,因此 t1 同步应当被暂停。当进展到右图时,t1、t2 分表都出现了相同的 DDL,因此此时可以将这条 DDL 应用到下游并恢复 t1、t2 的同步。\

在某些情况下,t1、t2 可能位于一个 binlog 流之中,因此上图中看似独立的流的暂停与恢复,实际实现为在同一个 binlog 流中跳过事件及回滚同步位置。

如上图,我们需要在事件 1、2、4、5、6 之后同步事件 3,因此在 binlog 流中首次遇到事件 3 时跳过,并在事件 6 完成之后重新从事件 3 开始同步,并跳过已经同步的 4、5、6 事件。

悲观协调模式限制

可以看到这种协调模式解决方法有如下的限制:

  • 出现 DDL 同步事件时分表会暂停,会导致同步延迟增加。这可能会导致恢复同步时,上游 binlog 已经被清理
  • 不支持只变更部分分表以进行灰度测试时的场景。灰度期间其余分表的同步会暂停。此外如果灰度测试结果是回滚时,无法恢复同步
  • 要求所有分表以相同的顺序出现 DDL 同步事件
  1. 如果分表由于误操作而进入 DDL 不一致的状态,修复操作较为复杂
  2. 对于 DM 的使用者而言,可能无法控制上游 DDL 的发起从而无法满足条件\

因为悲观协调模式的种种限制,DM 也提供了新的乐观协调模式,我们将在后续的文章中具体介绍,希望大家能够在深入了解两种协调模式的原理和使用限制后,根据场景选择合适的模式进行分库分表的合并迁移。

这篇关于DM 分库分表 DDL “悲观协调” 模式介绍丨TiDB 工具分享的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/884295

相关文章

Java数字转换工具类NumberUtil的使用

《Java数字转换工具类NumberUtil的使用》NumberUtil是一个功能强大的Java工具类,用于处理数字的各种操作,包括数值运算、格式化、随机数生成和数值判断,下面就来介绍一下Number... 目录一、NumberUtil类概述二、主要功能介绍1. 数值运算2. 格式化3. 数值判断4. 随机

linux进程D状态的解决思路分享

《linux进程D状态的解决思路分享》在Linux系统中,进程在内核模式下等待I/O完成时会进入不间断睡眠状态(D状态),这种状态下,进程无法通过普通方式被杀死,本文通过实验模拟了这种状态,并分析了如... 目录1. 问题描述2. 问题分析3. 实验模拟3.1 使用losetup创建一个卷作为pv的磁盘3.

使用Navicat工具比对两个数据库所有表结构的差异案例详解

《使用Navicat工具比对两个数据库所有表结构的差异案例详解》:本文主要介绍如何使用Navicat工具对比两个数据库test_old和test_new,并生成相应的DDLSQL语句,以便将te... 目录概要案例一、如图两个数据库test_old和test_new进行比较:二、开始比较总结概要公司存在多

MySQL8.2.0安装教程分享

《MySQL8.2.0安装教程分享》这篇文章详细介绍了如何在Windows系统上安装MySQL数据库软件,包括下载、安装、配置和设置环境变量的步骤... 目录mysql的安装图文1.python访问网址2javascript.点击3.进入Downloads向下滑动4.选择Community Server5.

Java实现状态模式的示例代码

《Java实现状态模式的示例代码》状态模式是一种行为型设计模式,允许对象根据其内部状态改变行为,本文主要介绍了Java实现状态模式的示例代码,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来... 目录一、简介1、定义2、状态模式的结构二、Java实现案例1、电灯开关状态案例2、番茄工作法状态案例

CentOS系统Maven安装教程分享

《CentOS系统Maven安装教程分享》本文介绍了如何在CentOS系统中安装Maven,并提供了一个简单的实际应用案例,安装Maven需要先安装Java和设置环境变量,Maven可以自动管理项目的... 目录准备工作下载并安装Maven常见问题及解决方法实际应用案例总结Maven是一个流行的项目管理工具

Java中基于注解的代码生成工具MapStruct映射使用详解

《Java中基于注解的代码生成工具MapStruct映射使用详解》MapStruct作为一个基于注解的代码生成工具,为我们提供了一种更加优雅、高效的解决方案,本文主要为大家介绍了它的具体使用,感兴趣... 目录介绍优缺点优点缺点核心注解及详细使用语法说明@Mapper@Mapping@Mappings@Co

10个Python自动化办公的脚本分享

《10个Python自动化办公的脚本分享》在日常办公中,我们常常会被繁琐、重复的任务占据大量时间,本文为大家分享了10个实用的Python自动化办公案例及源码,希望对大家有所帮助... 目录1. 批量处理 Excel 文件2. 自动发送邮件3. 批量重命名文件4. 数据清洗5. 生成 PPT6. 自动化测试

使用Python实现图片和base64转换工具

《使用Python实现图片和base64转换工具》这篇文章主要为大家详细介绍了如何使用Python中的base64模块编写一个工具,可以实现图片和Base64编码之间的转换,感兴趣的小伙伴可以了解下... 简介使用python的base64模块来实现图片和Base64编码之间的转换。可以将图片转换为Bas

使用Java实现一个解析CURL脚本小工具

《使用Java实现一个解析CURL脚本小工具》文章介绍了如何使用Java实现一个解析CURL脚本的工具,该工具可以将CURL脚本中的Header解析为KVMap结构,获取URL路径、请求类型,解析UR... 目录使用示例实现原理具体实现CurlParserUtilCurlEntityICurlHandler