一、 背景

在早期从MySQL到TiDB实施同步操作过程中,我们大多数用的是mydumper+loader进行整体全量备份的导出,之后拿到meta信息后,通过syncer实现增量同步,整体操作起来比较麻烦,涉及的配置文件较多,其基本原理就是Syncer 通过把自己注册为一个 MySQL Slave 的方式,和 MySQL Master 进行通信,然后不断读取 MySQL Binlog,进行 Binlog Event 解析,规则过滤和数据同步。其架构如下:

而后pingcap官方推出了TiDB Data Migration (DM)套件,这一套件极大地降低了同步工具使用的门槛。

DM是一体化的数据迁移任务管理平台,支持从 MySQL 或 MariaDB 到 TiDB 的全量数据迁移和增量数据复制。使用 DM 工具有利于简化错误处理流程,降低运维成本。后续更是有dm-portal工具方便dba通过图形化界面的方式进行选择性导出和自动生成配置文件,虽然有一些小bug和不够人性化的方面,但无伤大雅,可惜的是这个项目最后咨询官方得知被砍掉了,不再进行维护。

二、 原因

我有幸从DM内测版本开始就接触和使用这一工具,直至其最新版1.0.6,见证了DM功能不断的完善,真切体会到了这一工具给我们带来的帮助,我认为这是每一个DBA和TiDB使用者都应该了解甚至熟练掌握的工具,因为大多数场景下,我们使用TiDB并不是全新的系统上去直接建库建表,而是从MySQL迁移过来,先进行性能对比和测试,而后进行数据迁移的,因此熟练掌握DM工具可以让你的工作事半功倍。

三、架构

集群配置

集群版本:v3.0.5

集群配置:普通SSD磁盘,128G内存,40 核cpu

tidb21 TiDB/PD/pump/prometheus/grafana/CCS

tidb22 TiDB/PD/pump

tidb23 TiDB/PD/pump

tidb01 TiKV

tidb02 TiKV

tidb03 TiKV

tidb04 TiKV

tidb05 TiKV

tidb06 TiKV

tidb07 TiKV

tidb08 TiKV

tidb09 TiKV

tidb10 TiKV

tidb11 TiKV

tidb12 TiKV

tidb13 TiKV

tidb14 TiKV/DM-prometheus/DM-grafana/DMM

tidb15 TiKV/DMW1

tidb16 TiKV/DMW1

正常来说,官方建议抽出单独的机器来部署DM,且推荐每个节点上部署单个 DM-Worker 实例。除非机器拥有性能远超 TiDB 软件和硬件环境要求中推荐配置的 CPU 和内存,并且每个节点配置 2 块以上的硬盘或大于 2T 的 SSD,才推荐单个节点上部署不超过 2 个 DM-Worker 实例。而我们的线上环境机器比较吃紧,所以一直以来都是和TiKV进行混部的,例如上述架构中,选取了tidb14,tidb15,tidb16进行dm相关的软件部署。所幸运行起来效果还可以,但有条件的建议大家还是老老实实按照官方文档,单独部署。

DM架构

DM架构如上图所示,主要包括三个组件:DM-master,DM-worker 和 dmctl。

DM-master 负责管理和调度数据迁移任务的各项操作

DM-worker 负责执行具体的数据迁移任务

dmctl 是用来控制 DM 集群的命令行工具

具体的功能本文不再赘述,可参考官方文档了解每一个模块的详细功能

DM特性

Table routing 合并迁移

Block & allow table lists 白名单

Binlog event filter binlog级别过滤

Shard support 合库合表

四、新特性

dm从内测版本开始,每一个版本的迭代都修复和新加入了不少功能,这里我单独拎出来1.0.5这个版本,因为从这个版本开始,它支持了以前从来没有但又让人早就期盼已久的功能:online ddl的支持。

众所周知,MySQL在数据量大了后,没有人会直接去对原表进行alter,大多数人都通过第三方工具pt-online-schema-change或者gh-ost来进行改表,以此削减改表期间对线上业务的影响。而早期的dm不支持该功能时,每次上游改完表后,由于临时表(_xxxx_new,_xxx_gho等)不在白名单里,会直接导致下游tidb丢失该DDL,引发同步异常报警。当然,如果你是全库同步,那自然不会有这个问题,但绝大多数场景下都是部分表导入到TiDB,用到了白名单功能的情况下就会导致该问题出现。而1.0.5版本后,这便不再是问题,虽然目前仅仅只能同时支持一种改表工具,但对比之前来说,无疑是我认为最好的改进,还没用的朋友们不妨试一试。

例如:

上游通过pt-online-schema-change工具为表helei5新增一列

--alter="ADD column hl2 varchar(10) not null default '';" D=h_2,t=helei5

先看下没有配置跳过的情况

几个关键的词:

skip event 因为不在白名单中被跳过

skip event, need handled ddls is empty ,中间表因为被过滤掉在下游不存在,

所以提示is empty,也被跳过RENAME TABLE `h_2`.`helei5` TO `h_2`.`_helei5_old`",

"RENAME TABLE `h_2`.`_helei5_new` TO `h_2`.`helei5`

rename操作在上游为了保证原子性是一条SQL实现表名互换的,

我们可以看到,好在拆分后也依旧是被跳过的,这是因为中间表不存在

rename的ddl里部分表例如_helei5_new是空的,所以整个SQL不会被执行

"RENAME TABLE `h_2`.`helei5` TO `h_2`.`_helei5_old`的话被执行了是我们不希望看到的

此时task状态依旧是running,但下游已经没有新增的列

{

"taskName": "task_4369",

"taskStatus": "Running",

"workers": [

“192.168.1.248:8262"

]

此时插入包含新列h2的数据

mysql> insert into helei5 values(14,'cccc','pt alter');

这个时候dm就会报错

{

"taskName": "task_4369",

"taskStatus": "Error - Some error occurred in subtask. Please run `query-status task_4369` to get more details.",

"workers": [

“192.168.1.248:8262"

]

报错信息是:

msg": "[code=36027:class=sync-unit:scope=internal:level=high] current pos (4369-binlog|000001.000021, 62771055): gen insert sqls failed, schema: h_2, table: helei5: Column count doesn't match value count: 2 (columns) vs 3 (values)

点位:

sync": {

"totalEvents": "3",

"totalTps": "0",

"recentTps": "0",

"masterBinlog": "(4369-binlog.000021, 62774081)",

"masterBinlogGtid": "1c3add9b-7c26-11e7-81bf-70e28411103e:1-910975,1d1872fd-7c26-11e7-81bf-70e284110e52:1-3,200ccab3-f941-11e8-b6de-6c92bf96384c:1-800846",

"syncerBinlog": "(4369-binlog|000001.000021, 62765733)",

因为少列,所以报错,我们在下游添加列,然后跳过

mysql> alter table helei5 add column h2 varchar(10) not null default '';

跳过语句是:

» sql-skip --worker=192.168.1.248:8262 --binlog-pos=4369-binlog|000001.000021:62765733 task_4369

{

"result": true,

"msg": "",

"workers": [

{

"result": true,

"worker": "",

"msg": ""

}

]

}

dm-worker的日志有如下内容:

[2020/05/14 15:48:05.883 +08:00] [INFO] [operator.go:136] ["set a new operator"] [task=task_4369] [unit="binlog replication"] ["new operator"="uuid: b52784e4-e804-46f5-974c-ca811a34dc30, pos: (4369-binlog|000001.000021, 62765733), op: SKIP, args: "]

执行恢复任务

» resume-task task_4369

{

"taskName": "task_4369",

"taskStatus": "Running",

"workers": [

“192.168.1.248:8262"

在添加online-ddl-scheme: "pt"参数后,下游成功读取到pt-online-schama-change加的新列:

gh-ost工具同理:

几个关键词:

ghc表的创建DM是忽略的:

prepare to handle ddls

skip event, need handled ddls is empty

gho表的创建和新DDL也是忽略的,而是把该 DDL 记录到 dm_meta.{task_name}\_onlineddl 以及内存中:

prepare to handle ddls

skip event, need handled ddls is empty

del表的创建也是忽略的:

rename /* gh-ost */ table `h_2`.`helei5` to `h_2`.`_helei5_del`, `h_2`.`_helei5_gho` to `h_2`.`helei5`

不执行 rename to _helei5_del。当要执行 rename ghost_table to origin table 的时候,并不执行 rename 语句,而是把记录在内存中的 DDL 读取出来,然后把 ghost_table、ghost_schema 替换为 origin_table 以及对应的 schema,再执行替换后的 DDL。

操作完日志会有:

finish online ddl and clear online ddl metadata in normal mode

在添加online-ddl-scheme: "gh-ost"的参数后,下游也读取到了加的列

五、1062的踩坑

在早期,我们有一个业务通过DM同步到TiDB,但每过几个小时后,同步总是中断,而每次我们人工resume task又能恢复,咨询后得知resume操作后,dm内部前几分钟是debug模式,执行的replace。

当时的报错内容如下:

>> query-status task_3306

...

...

"msg": "[code=10006:class=database:scope=not-set:level=high] execute statement failed: commit: Error 1062: Duplicate entry '21277ed5f5e7c3b646a5229269d54d3a7fccc08bf34c8f2113fdd4df62f4a229' for key 'clientid'\ngithub.com/pingcap/dm/pkg/terror.(*Error).Delegate\n

>>query-error task_3306

"errorSQL": "[tp: insert, sql: INSERT INTO `360sudi`.`client` (`id`,`clientid`,`toid`,`updatetime`) VALUES (?,?,?,?);, args: [4102315138 62ba2a78af090ab1337c6b62f8dedfc8b6338007cdeb5a7ea4e7f4b4c23e3e0c 3250350869 2019-11-21 19:54:56], key: 4102312246, ddls: []

用自增id的主键查:

[helei@db01 ~]$ curl http://192.168.1.1:10080/mvcc/key/360/client/4102315138

{

"key": "7480000000000011945F7280000000F4845C82",

"region_id": 2278436,

"value": {

"info": {

"writes": [

{

"type": 3,

"start_ts": 412703076417274370,

"commit_ts": 412703076417274370

}

]

}

}

}

根据查询出来的 commit-ts 使用 pd-ctl tso 命令看下在下游已经存在的记录提交的时间

[root@tidb helei]# /data1/tidb-ansible-3.0.5/resources/bin/pd-ctl -i -u http://192.168.1.2:2379

» tso

Usage: tso

» tso 412703076417274327

system: 2019-11-21 19:54:57.124 +0800 CST

logic: 471

» tso 412702903507091560

system: 2019-11-21 19:43:57.524 +0800 CST

logic: 104

»

查找 dm-worker 日志中跟这个记录相关的内容

-binlog.000020, 185499141), relay-binlog-gtid = "]

[2019/11/21 19:54:47.710 +08:00] [INFO] [syncer.go:2004] ["binlog replication progress"] [task=task_3306] [unit="binlog replication"] ["total binlog size"=378940822] ["last binlog size"=378533105] ["cost time"=30] [bytes/Second=13590] ["unsynced binlog size"=0] ["estimate time to catch up"=0]

[2019/11/21 19:54:47.710 +08:00] [INFO] [syncer.go:2029] ["binlog replication status"] [task=task_3306] [unit="binlog replication"] [total_events=1528442] [total_tps=1455] [tps=40] [master_position="(3306-binlog.000020, 185616633)"] [master_gtid=] [checkpoint="(3306-binlog|000001.000020, 185616633)(flushed (3306-binlog|000001.000020, 185484711))"]

[2019/11/21 19:54:57.157 +08:00] [ERROR] [db.go:269] ["execute statements failed after retry"] [task=task_3306] [unit="binlog replication"] [queries="[INSERT INTO `360sudi`.`client` (`id`,`clientid`,`toid`,`updatetime`) VALUES (?,?,?,?);]"] [arguments="[[4102315138 62ba2a78af090ab1337c6b62f8dedfc8b6338007cdeb5a7ea4e7f4b4c23e3e0c 3250350869 2019-11-21 19:54:56]]"] [error="[code=10006:class=database:scope=not-set:level=high] execute statement failed: commit: Error 1062: Duplicate entry '62ba2a78af090ab1337c6b62f8dedfc8b6338007cdeb5a7ea4e7f4b4c23e3e0c' for key 'clientid'"]

比较下第二个步骤查询出来的时间和第三个步骤查询出来的时间

第二个步骤 2019-11-21 19:54:57.124 +0800 CST

第三个步骤 2019/11/21 19:54:57.157 +08:00

第二个步骤2019-11-21 19:43:57.524的时间,在第三个步的worker日志里未找到相关

我们尝试过:

1.将dm下游配置为单一tidb而非tidb的lvs,防止多个ip写入ntp引起毫秒级的误差(无果)

2.task文件针对syncer的worker进行限制,只让一个syncer进行同步(无果)

3.业务变更为replace into,开始测试

改syncer worker count的时候,光rolling_update是没用的,需要dm-ctl去stop/start task才可以生效

可以看到,15:25起,qps在syncer worker count配置为16后瞬间从256涨到4k

限制worker,库里也有多个而非一个进程

而单个进程依然会报错1062不说,还会导致延迟不断增加,之后我们又调整会16后,能看到快速追上上游主库日志

最终我们是通过业务更改replace into解决该问题

六、DM大批量导入调参

集群稳定运行旗舰,有新数据要通过DM灌入,此时会影响已有集群的稳定性

如下图所示,能看到DM导入期间集群响应出现延迟

我们通过如下参数从原值调到-新值规避了这一问题,但每个集群场景和配置完全不同,适度谨慎调整,调整前应了解每一个参数的含义,如下仅做参考

raftstore:

apply-pool-size: 3-4

store-pool-size: 3-4

storage:

scheduler-worker-pool-size: 4-6

server:

grpc-concurrency: 4-6

rocksdb:

max-background-jobs: 8-10

max-sub-compactions: 1-2

七、限制

版本限制:

数据库版本

5.5 < MySQL 版本 < 8.0

MariaDB 版本 >= 10.1.2

仅支持 TiDB parser 支持的 DDL 语法

上下游 sql_model 检查

上游开启 binlog,且 binlog_format=ROW

DM不支持的类型:

1)一次删除多个分区的操作则会报错:

alter table dsp_group_media_report drop partition p202006 ,p202007 ;

2)drop含有索引的列操作会报错

Alter table dsp_group drop column test_column;

DM-portal限制:

●在早期还没有dm-portal自动化生成task时,我们都是自行编写DM的task同步文件

●后来有了dm-portal自动化生成工具,只要图形页面点点点就可以了

但该工具目前有一个问题是,没有全库正则匹配,几遍你只勾选一个库,他底层是默认把每张表都给你配置一遍。这就会出现当上层MySQL新创建某张表的时候,下游会被忽略掉,例如当你使用改表工具gh-ost或者pt-online-schema-change,你的临时表都会被当做为不在白名单内而被忽略,这个问题使用者需要注意。我们也已经反馈给了官方。且如文章第四节所示,已于1.0.5版本修复。

DM-worker清理配置:

[purge]

interval = 3600

expires = 7

remain-space = 15

关于relay-log,默认是不清理的,就和mysql的expire_logs_days一样,这块可以通过dm-worker的配置文件来进行配置,例如将expires配置为7,代表7天后删除:

#默认expires=0,即没有过期时间,而remain-space=15意思是当磁盘只剩于15G的时候开始尝试清理,这种情况我们极少会碰到,因此这个清理方式其实基本上是用不到的。所以建议有需要删除过期relay-log的小伙伴,直接配置expires保留天数就可以了。

DM导入完成后,应该提供是否在完成后自动删除全备文件的选项,可以默认不删,由使用者决定是否删除。

从使用者角度来说,全量备份目录无论是全量一次性导入还是all增量同步,后续都不会再使用到。如果dm-worker和tikv混部,会导致全备文件占据大量磁盘空间,引起tikv region评分出现异常,导致性能下降,这一点如果有相同的架构的朋友们需得注意。

默认调度策略是当磁盘剩余的有效空间不足 40% ,处于中间态时则同时考虑数据量和剩余空间两个因素做加权和当作得分,当得分出现比较大的差异时,就会开始调度。

所以DM导入完成后,要记得删除全量备份,就是dumped_data.task_xxx文件夹,这个全量备份一般都会比较大,而且默认是不删除的,也没有配置项。如果dm-worker和tikv混部,就会出现某个tikv节点磁盘已使用率高于其他,这时pd的store region score就会相比其他节点出现异常。引起性能抖动和duration升高

八、总结和感慨

零零散散,大大小小的分享也做了很多了,从小白用户第一次在2019年7月接触TiDB,到入选核心成员组,到MVA,到DEVCON 2020作为嘉宾宣讲360在TiDB的分享,再到后续获TUG最具有影响力内容奖章,笔者一直都是本着分享才能让人进步的态度,毫无保留去分享技术干货。因为我真真切切的感受到了TiDB产品本身,以及TiDB社区在不断的做大,做强。就拿我司来说,360集团目前已经8个业务线在使用,4套集群,总数据量接近190TB,稳定流畅运行。目前12月份还接了一个大部门的80人TiDB内部培训,从我自己来说,我要感谢TiDB,感谢社区,我分享的同时,也有很多大牛帮助我改正文中的错误,让我自己也有了进一步的提升。同时我还认识了很多的很多志同道合的朋友,有美团,58同城,新东方,伴鱼,汽车之家,京东数科等等,我愿意进一步去毫无保留的分享,来认识更多的朋友。

mysql tidb 删除延迟_TiDB DM踩坑实践总结相关推荐

  1. 警惕参数变化,MySQL 8.0 升级避免再次踩坑

    MySQL 8.0新特性专栏目录 <MySQL开发规范>过时了,视图查询性能提升了一万倍 你真的会用EXPLAIN么,SQL性能优化王者晋级之路 索引三剑客之降序索引和不可见索引 千呼万唤 ...

  2. eslint 无法格式化ts_vscode-eslint的踩坑实践--typescript无法格式化

    Apple iPhone 11 (A2223) 128GB 黑色 移动联通电信4G手机 双卡双待 4999元包邮 去购买 > vscode-eslint的踩坑实践--typescript无法格式 ...

  3. 前端静态服务踩坑实践

    前言 随着前端项目的增大,越来越多时候会把动静态资源进行分离部署,对于分离部署时常常涉及到代理转发的问题,专网项目主要使用 nginx + docker + k8s的部署方式,本文主要分享一些相关项目 ...

  4. mysql mycat one_Mycat 整合 MySQL 8.x 踩坑实践

    Mycat 目前还未全面支持MySQL 8以上的版本,可能会导致一些问题,例如Mycat连接MySQL 8时可能会报密码错误,因为新版的密码加密方式与旧版不一样.还有就是时区问题,新版的连接方式需要增 ...

  5. linux python虚拟环境 error_阿里云Linux系统配置python3-虚拟环境-mysql --踩坑实践(Ubuntu系统转centOS7)...

    序言:个人使用阿里云的服务器,Ubuntu系统时在创建虚拟环境处卡住,多次修改无果后改用CentOS系统配置环境成功,但是其中也是尝试多次,这里就把自己找的能够配置成功的方法整理起来,以备后续有相关配 ...

  6. MySQL导入官方数据库world防踩坑完全操作

    1.在MySQL官方网站下载官方数据集world,链接.下载zip格式文件然后解压即可,是一个名叫world.sql的文件 2.打开电脑中mysql安装目录下的my.ini文件,找到secure_fi ...

  7. 这个 MySQL bug 99% 的人会踩坑!

    这周收到一个 sentry 报警,如下 SQL 查询超时了. select * from order_info where uid = 5837661 order by id asc limit 1 ...

  8. Logstash同步mysql一对多数据到ES(踩坑日记系列)

    场景: Logstash .Kibana.ES版本:6.3.1. 使用Logstash从mysql同步用户和用户所有的宠物到ES中. 希望的格式: "register_name": ...

  9. 4、Mysql 主从复制报错[ERROR] [MY-013117] 踩坑

    2020-07-01T14:34:42.709318Z 12 [ERROR] [MY-013117] [Repl] Slave I/O for channel '': Fatal error: The ...

  10. mysql 结束符报错_【踩坑记录】MySQL 实现自定义递归函数

    因项目需要,需根据某个商品类别path,查询该类别下的所有子类别 表  goods-categories(path,parent_id,id) 该处使用的表为临时创建的表 t1(id,parent_i ...

最新文章

  1. 题目:任意给定一个浮点数,计算这个浮点数的立方根。(基于二分法和牛顿迭代法)(基于Java实现)
  2. linux 报错 ip_conntrack version 2.4 (8192 buckets, 65536 max) - 304 bytes per conntrack 解决方法
  3. Python:SMOTE算法——样本不均衡时候生成新样本的算法
  4. ASP.NET中Json的处理
  5. CentOs基础操作指令(运行级别)
  6. Python基础教程笔记——条件,循环和其他语句
  7. 工程数学(数值分析)第五讲:数据拟合
  8. JAVA Metrics 度量工具使用介绍
  9. Python 操作 mongodb 数据库
  10. mac版 SimHei添加教程
  11. 【chrome插件开发一】初始chrome插件——helloWorld
  12. linux 网络 eth1 lo,br-lan、eth0、eth1及lo (转)
  13. python写的ROS激光雷达扇形滤波
  14. C语言位操作中的置0和置1
  15. 红米K40使用半个月,谈谈上手体验,“优缺点”非常明显!
  16. 安卓版的PanDownload 下载网盘资源
  17. 5.雅思口语——别再用delicious food啦
  18. 国三数据库系统工程师与软考中的数据库工程师,谁的难度更高?
  19. Integrated Product Development
  20. 什么是函数的副作用——理解js编程中函数的副作用

热门文章

  1. HDU 1728 优化的BFS
  2. Android第七讲笔记(圆形图片,网络图片,下拉刷新,上拉加载)
  3. 解决国外资源下载速度过慢的问题
  4. Raspberry Pi with Node.js and Arduino
  5. Android Q 上的Biometric生物识别之Fingerprint指纹识别流程
  6. 华硕笔记本电脑win10系统一键重装教程分享
  7. Java自定义组合控件
  8. 通过tasker实现朗读微信QQ文字消息
  9. Ubuntu deb文件 安装 MySQL
  10. linux .deb文件安装