常见问题排查之 -- DM 主键冲突的原因及排查思路
作者: 小王同学原文来源:https://tidb.net/blog/404b2fe0
现象
DM 出现主键冲突时,报错如下:
原理
排查这个问题,首先要确认是在哪个阶段出现的主键冲突。通常在全量迁移阶段。并且在 tidb.log 中的报错可以看到哪个表哪个 key 的冲突:
然后需要理解下各个阶段的原理,才好解决什么情况下出现冲突。
全量迁移阶段
DM 中 load 处理单元: 全量迁移阶段默认会把 position 记录到下游的 *_loader_checkpoint 表中。写 position 和数据本身在一个事务里,同步写入下游,即 全量迁移阶段位点是进行实时更新。
loader 处理过程:loader 会把 position 记录到下游 tidb_loader 库 ,写 position 和数据本身在一个事务里,同步写入下游。但如果实际数据已经写到下游,但出现 connection timeout 或者下游 oom,commit 后没有收到返回,这时问题来了,loader 判断有点问题,会重试,而 loader 的 sql 是原生的 insert 及 update,这时就会出现主键冲突的报错( loader 最新的 pr 解决了错误重试的问题,只对明确能重试的错误进行重试)
注意:v1.0.0-v1.0.4 版本 DM loader 阶段存在 bug,checkpoint 位点没有记录导致数据重复导入,出现 Duplicate entry 的问题。如版本低于 1.0.5,优先建议升级。
增量复制阶段
DM 中 sync 处理单元:position 是异步记录在 *_syncer_checkpoint 表中。
2.0 版本异步更新机制可以参考该代码
syncer 处理过程:与 loader 不同的是,position 是异步记录在 syncer.meta 中。配置文件中 syncer.meta 的作用是可以用来制定增量阶段的开始位置。
syncer 中有一个参数 safe-mode,当 safe-mode = true 的时候,会用 replace 替换 insert 语句,用 delete + replace 替换 update 语句。
如果 syncer insert timeout,syncer 进程会退出。然后 syncer 启动的时候,前几分钟强制 safe mode = true,会从靠前一点的问题复制,这种可以保证不会出现主键冲突的问题(实现 reenactment);几分钟后,会设置为用户设置的值,默认为 false(这在正常同步阶段是没有问题的,因为故障后启动时会改为 true),默认 false 的原因主要是考虑性能。
从上述原理看,增量复制阶段是不会出现主键冲突的,只有 全量迁移阶段才会出现主键冲突。增量复制阶段如果报错主键冲突,大概率是上游存在重复数据,以下分析均是假设 全量迁移阶段出现主键冲突。
分析步骤
首先判断 DM 是在同步过程中出现主键冲突,还是重启同步任务后报错主键冲突,根据不同的情况分析对应的原因。
知识点引入
dm_meta 即 meta-schema,是下游数据库中存放断点信息的数据库。全量迁移阶段以及 增量复制阶段均支持断点续传,断点信息从 dm_meta 中获取,即断点信息丢失,则重新进行数据同步。注意:全量迁移阶段位点实时更新,而 增量复制阶段位点是非实时更新的。
1. 重启同步任务后报错主键冲突
原因 1: 用户更改 task 任务名
原同步任务已经导入部分数据到下游 TiDB 集群中,后因某种原因更改 task name,导致 dm_meta 未记录该 task name 的断点信息,重启同步任务后,dm_meta 中不存在该 task name 的断点信息,因此会重新进行 dump 以及 load 操作,而此时下游数据存在从而报错主键冲突。
原因 2:task 配置中设置 remove-meta:true
注意:在 DM 2.0.x 里,已经把其从配置文件移动到命令行参数,这样就只会在明确指定时生效一次。
remove-meta 表示是否在任务同步开始前强制移除该任务名对应的 checkpoint 等 meta 信息,包括 xxx_loader_checkpoint、xxx_syncer_checkpoint、xxx_onlineddl 等保存同步断点信息的记录,之后该任务会重新开始导入或同步,包括从上游 dump 数据并覆写没有清理的下游数据。正常同步时,设置为 false 即可;只有在需要重置整个数据同步任务时才应将该参数设置为 true(该参数只会清理位点,需要手动把上次同步的库表清理掉),并在同步正常后改回 false,避免下次任务中断重启后再次重置同步任务。
原因 3: 手动误删除 dm_meta 的库或者 checkpoint 位点
因误操作将下游 dm_meta 数据库删除或者删除了该库下的表的信息,导致位点信息被清空,任务重新开始导入或同步时,因存在未清理的数据,导致主键冲突。
2.DM 同步过程中报错主键冲突
2.1. 全量迁移阶段报错主键冲突可能的原因以及排查方法
1)首先需要查看 dm-worker.log 日志,找到对应的 duplicate key 的记录,并进入下游数据库确认下游数据是否已存在
2)需要是否是上游数据重复导致主键冲突
在 dump 文件中 grep 冲突的主键值,存在多个,则上游存在冲突数据,需要从上游解决该问题(多个主键相同的值同步到下游同一张表中)
grep 1292790 ./dumped_data.xxx/*
#1292790 表示冲突的主键值,用户需根据自己主键冲突的情况自行查找
3)根据冲突主键的 MVCC 版本以及 dm_meta 中的位点信息具体分析
1. 利用 tidb API 查看主键冲突的行的 mvcc 版本,以此来确认该行数据插入数据库的时间
注意:该操作需要保留现场,该操作是从下游 TiDB 中查询。
# 主键为 int 类型,handle 即 int 类型主键
curl [http://{TiDBIP}:10080/mvcc/key/{db}/{table}/{handle]()}
# 主键为非整数类型
select _tidb_rowid from xxx where trade_no=‘190606LI8OODRTZA5XX1’;
curl [http://{TiDBIP}:10080/mvcc/key/{db}/{table}/](){_tidb_rowid}
根据上述命令得到如下结果:
下一步操作为根据 pd-ctl 将 commit_ts 转化为对应的时间,即解析 tso
注:也可以在 TiDB 中调用 select TIDB_PARSE_TSO(415345529804292097); 获取对应时间
2. 在 dm_meta 查询 min(create_time) 来获得 load 第一个文件时的时间,可以认为是 全量迁移阶段的开始时间
3. 在 dm_meta 中查看 xxx_loadder_checkpoint 表查看该文件 test.sbtest5.000000005.sql 的详细信息 image.png
4. 从 dm-worker 中 grep 查看该主键所在的 .sql 文件出现的时间以及次数
冲突的主键(1292790)所在的文件为 test.sbtest5.000000005.sql
grep test.sbtest5.000000005.sql dm-worker.log
结论
情况 1:上游数据存在冲突的情况
判断依据:dump 中的文件 grep 到多个主键值
解决方法:从上游数据入手,避免重复数据,或者采用 lightning 全量导入数据,lightning 默认采用 replace into 方式写入
情况 2:全量导入数据之前,该主键数据已经存在于下游数据库中
判断依据:主键写入数据库的时间即(MVCC 时间)早于 load 的时间(min(create_time))
解决方法:如仅出现一次主键冲突的情况,可以将下游主键数据删掉,恢复同步任务即可;如多次出现主键冲突,建议删除下游数据以及为位点信息后,重新进行全量数据的导入
情况 3:由于位点信息被清理导致 sql 文件被重复导入
判断依据:根据以下信息可了解到在 全量迁移阶段开始后,因某种原因导致 sql 文件位点被删除,sql 文件被重复导入,导致主键冲突
同步任务 全量迁移阶段开始时间为:2020-03-17 11:57:36
该数据插入数据库的时间为: 2020-03-17 11:57:37
该文件 test.sbtest5.000000005.sql 记录的 创建时间以及更新时间都是 2020-03-17 12:20:29
从 dm-worker.log 中 grep test.sbtest5.000000005.sql 发现同步任务开始后,有两次导入该文件
解决方法:建议清空下游数据,重新导入
2.2.syncer 阶段报错主键冲突
syncer 指增量同步,如发生主键冲突导致报错退出,启动后的前 5 分钟内会自动开启 safe_mode,主要原因是由于 dm_meta 中 syncer 的 checkpoint 点是非实时更新,需要保证数据可重复插入。
syncer 阶段报错主键冲突,可以从以下三个方面排查:
上游存在重复数据,导致 syncer 报错主键冲突
多个数据源写入(DM 和 syncer 同时同步数据到下游)或者多个 IP 写入导致 syncer 报错主键冲突
TiDB 重试导致报错主键冲突(4.0.9 已修复)
其他未知 bug
版权声明: 本文为 InfoQ 作者【TiDB 社区干货传送门】的原创文章。
原文链接:【http://xie.infoq.cn/article/7fc17a25020253e5038cdbcbc】。文章转载请联系作者。
评论