dm分库分表ddl“乐观协调”模式介绍丨tidb工具分享(代码片段)

TiDB_PingCAP TiDB_PingCAP     2023-03-05     272

关键词:

前言

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

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

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

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

原理

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

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

(具体的设计可以参考 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

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

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

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

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

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

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

例子

三个分片合并同步到 TiDB

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

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;

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

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

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

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

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

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;

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

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

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

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

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

限制

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

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

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

dm中relaylog性能优化实践丨tidb工具分享(代码片段)

将转换后的binlogevent使用binlogwriter以relaylogfile的形式存储在本地的relaydirectory中。的机制,读取最近写入的文件并非通过磁盘,而是读取OS内存中的缓存,因此理论上影响有限。的存在,应用本身再增加一层缓存对latency的影响有... 查看详情

shardingsphere实践——shardingsphere介绍

目录一、分库分表1.为什么需要分库分表(1)突破性能瓶颈(2)提高可用性2.什么时候考虑分库分表3.如何分库分表(1)水平拆分与垂直拆分(2)水平分库分表策略(3)分成多少库多少表&#... 查看详情

干货丨数据库分库分表基础和实践

数据库架构的演变在业务数据量比较少的时代,我们使用单机数据库就能满足业务使用,随着业务请求量越来越多,数据库中的数据量快速增加,这时单机数据库已经不能满足业务的性能要求,数据库主从复制架构随之应运而生... 查看详情

分库分表vsnewsql数据库

参考技术A最近与同行科技交流,经常被问到分库分表与分布式数据库如何选择,网上也有很多关于中间件+传统关系数据库(分库分表)与NewSQL分布式数据库的文章,但有些观点与判断是我觉得是偏激的,脱离环境去评价方案好... 查看详情

tidb4业界使用情况

...据库扩展的问题。对于MySQL来讲,最直接的方案就是采用分库分表的水平扩展方式 查看详情

分库分表

分库分表在谈论数据库架构和数据库优化的时候,我们经常会听到“分库分表”、“分片”、“Sharding”…这样的关键词。让人感到高兴的是,这些朋友所服务的公司业务量正在(或者即将面临)高速增长,技术方面也面临着一... 查看详情

分库分表之后的搜索策略

所谓分库,就是把原来在一个库中的数据放到多个库中存储;分表就是把原来在一个表中的数据放到多个表中存储。这里不讨论分库分表的策略和具体实现,主要想记录的一点,就是分库分表后的搜索如何实现?工作中遇到的是... 查看详情

购物商城订单分库分表应该如何设计

目录1、为什么有分库分表2、分库分表模式分类2.1垂直分库2.2垂直分表2.3水平分库 查看详情

sharding-jdbc结合mybatis实现分库分表功能

...很大的情况下如何保证性能。今天我就给大家介绍数据库分库分表的优化,本文介绍mybatis结合当当网的sharding-jdbc分库分表技术(原理这里不做介绍)  首先在pom文件中引入需 查看详情

sharding-jdbc实现分库分表(代码片段)

前言:本篇文章主要介绍一下如何使用ShardingJDBC做分库分表。什么是分库分表比较传统的小型应用通常是一个项目使用一个数据库进行数据存储,这样的架构模式在数据量日益增长的情况下,数据库势必会成为性能瓶... 查看详情

水平分库分表的关键步骤和技术难点

在之前的文章中,我介绍了分库分表的几种表现形式和玩法,也重点介绍了垂直分库所带来的问题和解决方法。本篇中,我们将继续聊聊水平分库分表的一些技巧。分片技术的由来关系型数据库本身比较容易成为系统性能瓶颈,... 查看详情

分库分表shardingsphere

文章目录一、ShardingSphere二、ShardingJDBC实战1、核心概念2、测试项目介绍3、快速实战4、ShardingJDBC的分片算法NoneShardingStrategyInlineShardingStrategyStandardShardingStrategyComplexShardingStrategyHintShardingStrategy5、ShardingSphere 查看详情

分库分表理论概述

1.什么是分库分表一个库一个表拆分为N个库N个表分为垂直拆分,水平拆分2.为什么要分库分表随着业务发展,表的数量,以及单表数据量越来越大,而由于无法分布式部署(部分数据库支持),单台服务器资源(cpu内存,IO)的限制,... 查看详情

大众点评订单系统分库分表实践

转载至:http://tech.meituan.com/dianping_order_db_sharding.html背景原大众点评的订单单表早就已经突破两百G,由于查询维度较多,即使加了两个从库,优化索引,仍然存在很多查询不理想的情况。去年大量抢购活动的开展,使数据库达到... 查看详情

水平分库分表的关键问题及解决思路

在之前的文章中,我介绍了分库分表的几种表现形式和玩法,也重点介绍了垂直分库所带来的问题和解决方法。本篇中,我们将继续聊聊水平分库分表的一些技巧。分片技术的由来关系型数据库本身比较容易成为系统性能瓶颈,... 查看详情

mysql_分库分表

分库分表数据切分  通过某种特定的条件,将我们存放在同一个数据库中的数据分散存放到多个数据库(主机)上面,以达到分散单台设备负载的效果。数据的切分同时还能够提高系统的总体可用性,由于单台设备Crash之后,... 查看详情

tidb的数据迁移工具现已开源

...遵循Apache-2.0开源协议,允许用户自由地使用及修改。据介绍,DM(DataMigration)是一体化数据同步任务管理平台,支持从MySQL/MariaDB到TiDB的数据迁移、全量备份和MariaDB/MySQLbinlog增量同步,有助于减少操作成本和简化错误处理流程。架... 查看详情

分库分表shardingsphere(代码片段)

文章目录一、ShardingSphere二、ShardingJDBC实战1、核心概念2、测试项目介绍3、快速实战4、ShardingJDBC的分片算法NoneShardingStrategyInlineShardingStrategyStandardShardingStrategyComplexShardingStrategyHintShardingStrategy5、ShardingSphere 查看详情