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

2024-04-08 02:08

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

前言

DM 支持在线执行分库分表的 DDL 语句(通称 Sharding DDL),先前的文章中,我们介绍了悲观模式,即当上游一个分表执行某一 DDL 后,这个分表的迁移会暂停,等待其他所有分表都执行了同样的 DDL 才在下游执行该 DDL 并继续数据迁移。

悲观协调模式的优点是可以保证迁移到下游的数据不会出错,并且能兼容大部分的 DDL 语句,缺点是会暂停数据迁移而不利于对上游进行灰度变更、并显著地增加增量数据复制的延迟。有些客户可能会花数个月在单一分片执行 DDL,满意后才会更改其他分片的结构。在悲观同步的设定下,用来测试的分片的 DML 事件会大量积压,在恢复同步后无法正常运作。与此同时,悲观模式还要求所有分片必须以相同的顺序执行 DDL,否则会导致任务报错暂停。

为此,DM 提供新的乐观协调模式,在一个分表上执行的 DDL,自动修改成兼容其他分表的 DDL 语句后立即应用到下游,不会阻挡任何分表执行的 DML 的迁移。乐观协调模式适用于上游灰度更新、发布的场景,或者是对上游数据库表结构变更过程中同步延迟比较敏感的场景。

1.png

悲观协调和乐观协调的对比

原理

DM worker 的所有 DML 会直接同步到下游(出错时例外)。

DM worker 内嵌了一个小型 TiDB(通称 schema tracker),用来记录各个上游分表的表结构,当接收到来自上游的 DDL 后,会根据 schema tracker 里 DDL 的执行结果,把更新后的表结构转送给 DM master。DM master 将收到的不同分片的表结构合并成可兼容所有分片的 DML 的合成结构,即不同分片表结构的并集(此过程类似于 SQL 语句中的 JOIN 语句),然后根据合成的表结构和 DM worker 发来的表结构的不同处得到对应的 DDL 语句(即合成的表结构与原表结构的差集),同步到下游。

2.png

(具体的设计可以参考 DM: Manage DDLs on Sharded Tables by Maximizing Schema Compatibility

规则

乐观 DDL 表结构合并的规则简单来说就是对列属性定义了一个偏序关系,对不同表的同一列进行排序,选择该偏序关系中的极大元。对于不可比较的列,则返回错误

  • null < not null
  • no default < default(x)
  • varchar(x) < varchar(y), where x< y
  • utf8 < utf8mb4
  • char < varchar
  • tinyint < smallint < mediumint < bigint

对于被不存在或者被删除的列,我们把它定为最小的列

如初始时表结构是相同的。

3.png

tbl2 添加第三列。前两列相同;tbl1 的第三列为空,所以保留 tbl2 的第三列。

4.png

tbl2 删除第一列。第二列相同;tbl2 的第一列为空,所以保留 tbl1 的第一列。tbl1 的第三列为空,所以保留 tbl2 的第三列

5.png

tbl1 将第二列改为 varchar(10),由于 varchar(5) < varchar(10),所以保留 tbl1 的第二列

6.png

tbl1 重命名第二列。现在 tbl1 和 tbl2 的第二列名字不一样,无法比较,DM 无法确定最终的表结构,所以任务会报错

7.png

例子

三个分片合并同步到 TiDB

8.png

① 在上游增加一列 Level。
alter table tbl00 add column Level int unsigned not null;

9.png

tbl00, tbl01, tbl02 的并集 tblMerge 是 {ID,NAME,Level}
tblMerge 和 tbl 的差集是 {Level},所以 DDL 是 add column Level

此时下游 TiDB 要准备接受来自 tbl00 有 Level 的 DML、以及来自 tbl01 和 tbl02 没有 Level 的 DML,所以同步到下游时,自动改写成指定默认值的形式。
alter table tbl add column Level int unsigned not null default 0;

10.png

这时候各种 DML 毋需修改都可以同步到下游。
update tbl00 set Level = 9 where ID = 1;
insert into tbl02 (ID, Name) values (27, ‘Tony’);

11.png

② 在 tbl01 同样增加一列 Level。
alter table tbl01 add column Level int unsigned not null;

12.png

tbl00, tbl01, tbl02 的并集 tblMerge 是 {ID,NAME,Level}
tblMerge 和 tbl 的差集是 {},所以 DDL 为空

此时下游已经有相同的 Level 列了,所以 DM master 比较之后不做任何动作。

③ 在 tbl01 刪除一列 Name。
alter table tbl01 drop column Name;

13.png

tbl00, tbl01, tbl02 的并集 tblMerge 是 {ID,NAME,Level}
tblMerge 和 tbl 的差集是 {Level},所以 DDL 为空

此时下游仍需要接收来自 tbl00 和 tbl02 含 Name 的 DMLs,故不立删之,而是为这列也补上一个默认值。
alter table tbl alter column Name set default “”;

同样,各种 DML 仍可直接同步到下游。
insert into tbl01 (ID, Level) values (15, 7);
update tbl00 set Level = 5 where ID = 5;

14.png

④ 在 tbl02 增加一列 Level。
tbl00, tbl01, tbl02 的并集 tblMerge 是 {ID,NAME,Level}
tblMerge 和 tbl 的差集是 {Level},所以 DDL 为空
alter table tbl02 add column Level int unsigned not null;

15.png

此时所有分片都已有 Level 列,所以可以把作为兼容的默认值去掉。
alter table tbl alter column Level drop default;

⑤⑥ 在 tbl00 和 tbl02 各刪除一列 Name。
alter table tbl00 drop column Name;
alter table tbl02 drop column Name;

16.png

tbl00, tbl01, tbl02 的并集 tblMerge 是 {ID,Level}
tblMerge 和 tbl 的差集是 -{Name},此差集是有符号的,所以 DDL 是 drop column Name

到此步 Name 列也从所有分片消失了,所以可以安全从下游移除。
alter table tbl drop column Name;

17.png

限制

使用“乐观协调”模式有一定的风险,需要严格遵照以下方针:

  • 执行每个批次的 DDL 前和后,要确保每个分表的结构达成一致。
  • 进行灰度 DDL 时,最好只集中在一个分表上测试。
  • 灰度完成后,在其他分表上尽量以最简单直接的 DDL 迁移到最终的 schema,而不要重新执行灰度测试中对或错的每一步。
  • 例如:在分表执行过 ADD COLUMN A INT; DROP COLUMN A; ADD COLUMN A FLOAT;,在其他分表直接执行 ADD COLUMN A FLOAT 即可,不需要三条 DDL 都执行一遍。
  • 执行 DDL 时要注意观察 DM 迁移状态。当迁移报错时,需要判断这个批次的 DDL 是否会造成数据不一致。

更详细的介绍可参考官网文档

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


原文地址:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/884298

相关文章

MySQL慢查询工具的使用小结

《MySQL慢查询工具的使用小结》使用MySQL的慢查询工具可以帮助开发者识别和优化性能不佳的SQL查询,本文就来介绍一下MySQL的慢查询工具,具有一定的参考价值,感兴趣的可以了解一下... 目录一、启用慢查询日志1.1 编辑mysql配置文件1.2 重启MySQL服务二、配置动态参数(可选)三、分析慢查

Linux从文件中提取特定内容的实用技巧分享

《Linux从文件中提取特定内容的实用技巧分享》在日常数据处理和配置文件管理中,我们经常需要从大型文件中提取特定内容,本文介绍的提取特定行技术正是这些高级操作的基础,以提取含有1的简单需求为例,我们可... 目录引言1、方法一:使用 grep 命令1.1 grep 命令基础1.2 命令详解1.3 高级用法2

gorm乐观锁使用小结

《gorm乐观锁使用小结》本文主要介绍了gorm乐观锁使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录前言grom乐观锁机制gorm乐观锁依赖安装gorm乐观锁使用创建一个user表插入数据版本号更新总结前言乐观锁,顾名

基于Python实现进阶版PDF合并/拆分工具

《基于Python实现进阶版PDF合并/拆分工具》在数字化时代,PDF文件已成为日常工作和学习中不可或缺的一部分,本文将详细介绍一款简单易用的PDF工具,帮助用户轻松完成PDF文件的合并与拆分操作... 目录工具概述环境准备界面说明合并PDF文件拆分PDF文件高级技巧常见问题完整源代码总结在数字化时代,PD

setsid 命令工作原理和使用案例介绍

《setsid命令工作原理和使用案例介绍》setsid命令在Linux中创建独立会话,使进程脱离终端运行,适用于守护进程和后台任务,通过重定向输出和确保权限,可有效管理长时间运行的进程,本文给大家介... 目录setsid 命令介绍和使用案例基本介绍基本语法主要特点命令参数使用案例1. 在后台运行命令2.

Python按照24个实用大方向精选的上千种工具库汇总整理

《Python按照24个实用大方向精选的上千种工具库汇总整理》本文整理了Python生态中近千个库,涵盖数据处理、图像处理、网络开发、Web框架、人工智能、科学计算、GUI工具、测试框架、环境管理等多... 目录1、数据处理文本处理特殊文本处理html/XML 解析文件处理配置文件处理文档相关日志管理日期和

使用Python开发一个Ditto剪贴板数据导出工具

《使用Python开发一个Ditto剪贴板数据导出工具》在日常工作中,我们经常需要处理大量的剪贴板数据,下面将介绍如何使用Python的wxPython库开发一个图形化工具,实现从Ditto数据库中读... 目录前言运行结果项目需求分析技术选型核心功能实现1. Ditto数据库结构分析2. 数据库自动定位3

MySQL常用字符串函数示例和场景介绍

《MySQL常用字符串函数示例和场景介绍》MySQL提供了丰富的字符串函数帮助我们高效地对字符串进行处理、转换和分析,本文我将全面且深入地介绍MySQL常用的字符串函数,并结合具体示例和场景,帮你熟练... 目录一、字符串函数概述1.1 字符串函数的作用1.2 字符串函数分类二、字符串长度与统计函数2.1

使用IDEA部署Docker应用指南分享

《使用IDEA部署Docker应用指南分享》本文介绍了使用IDEA部署Docker应用的四步流程:创建Dockerfile、配置IDEADocker连接、设置运行调试环境、构建运行镜像,并强调需准备本... 目录一、创建 dockerfile 配置文件二、配置 IDEA 的 Docker 连接三、配置 Do

OpenCV在Java中的完整集成指南分享

《OpenCV在Java中的完整集成指南分享》本文详解了在Java中集成OpenCV的方法,涵盖jar包导入、dll配置、JNI路径设置及跨平台兼容性处理,提供了图像处理、特征检测、实时视频分析等应用... 目录1. OpenCV简介与应用领域1.1 OpenCV的诞生与发展1.2 OpenCV的应用领域2