DM同步无数据冲突报错唯一键冲突重启任务恢复

【 TiDB 使用环境】生产
【 TiDB 版本】5.4.0
【遇到的问题】mysql分库分表的表同步到后端tidb,目前只在一个mysql的db写入分库的表,但是报错了唯一冲突
【问题现象及影响】同步卡住需要人工重启任务
设置的是多个库分库同步,但是当前业务只使用了一个源端db的table。业务上:先自动请货,产生了一条,然后再点自动请货,然后会删除之前的数据(mysql源端)。
但是数据到tidb就报错了唯一键冲突,mysql端也是有唯一索引的,唯一值只有一条记录的。
注:dm任务配置的的safe_mode设置为false
请问:1.dm读取binlog 不是顺序读顺序写的吗?
2.为啥会出现此问题?

就是分表的表 只在一张源端表写入数据了,其他都是只有表结构。但是同步任务报错insert into 唯一键冲突了,重启任务的时候应该是自动改为replace into 所以重启同步恢复了吧。

请问是用 DM 将多个分表合并到同一个 TiDB 的表吗(合库合表)?多个表合并的场景要考虑分表之间键值是否唯一(https://docs.pingcap.com/zh/tidb/stable/dm-overview#使用限制

然后就是您说的,“自动清货”是用的什么 DML 语句呢?DM 会自动过滤掉 truncate 语句的(https://github.com/pingcap/tiflow/issues/5055 )。可以检查一下“自动清货”这个 SQL 是否有成功同步到下游。

binlog 是否顺序读写:是的。对同一个上游,DM 会绑定到同一个 worker,而这个 worker 在增量同步阶段是按照这个上游数据库产生 binlog 的顺序来拉取并消费 binlog 的。

是的,用 DM 将多个分表合并到同一个 TiDB 的表。
“自动清货”是用的insert–delete+insert.
分表之间键值是否唯一?这个是指的什么呢?唯一键的数据是否唯一吗?

对的。不仅在当前表里面唯一,在各分表里面唯一。比如说,三个分表都有一个 id 字段,如果这个 id 字段在分表间不唯一,就可能造成冲突。

这个确定是唯一的,因为其他的分表都还没有写数据,只有一张源表写入数据了。

而且源端这张表也是有唯一索引的,源端只有一条记录。

可以看看 log 和配置文件吗?在报了冲突之后,您有手动在下游查询这个键值是不是存在吗(检查一下 delete 语句是否有成功同步)

查询了数据是存在的。mysql端似乎是一个事务改多张表的。报错你看下截图


开发同事回复没有事务,看报错不止这张报冲突的表有报错。另外一个报错 context deadline exceeded。

补充下日志截图:

  1. 有 worker 的 log 吗(不是 dmctl 的输出,是 dm-worker.log,里面应该可以看到在下游执行的 SQL 语句,看一下这些重复的 key insert 和 delete 的次数和顺序;也可以看一下不同的 worker 之间是否 insert 了同一个 key)
  2. 图二看上去是下游有连接问题啊

worker的日志:2022/06/06 12:44:52.792 +08:00] [ERROR] [db.go:221] [“execute statements failed after retry”] [task=shard_h3_store] [unit=“binlog replication”] [queries="[DELETE FROM h3_store.t_store_delivery_apply_order_goods WHERE apply_order_goods_id = ? LIMIT 1]"] [ar
guments="[[983343172958568460]]"] [error="[code=10006:class=database:scope=not-set:level=high], Message: execute statement failed: begin, RawCause: sql: connection is already closed"]。显示是有连接关闭情况,这种情况影响同步?连接关闭会重试的吧?

在 log 里面搜一下这个重复的 key 的执行顺序吧,如果其他上游没有操作这个 key 的话应该很容易就发现为什么重复了

对的。这是重试之后失败了。看看 TiDB 集群的连接状况?

这个重试insert执行了很多次都是显示失败的。我再按你说的找找日志,感谢

[图片]
从日志来看,操作顺序是没错的,但是这insert-delete-insert三个操作都提示有报错应该都没执行才对。但是当时查询tidb目标端是有这条数据的。

您在重试任务之前有清空 TiDB 吗?现在 TiDB 集群和 DM 的连接恢复正常了吗?如果都失败了的话,DM 不会向 TiDB 写入任何数据才对。所以建议您确保 DM 和 TiDB 的连接之后,清空之前的数据(drop database),并重启任务(加上 --remove-meta,防止从之前的 checkpoint 开始同步),看一下是否还会出现这个问题

没有清空tidb的(是业务在使用的生产环境)直接重启任务,连接就都恢复正常了。如果清空数据相当于重新初始化了这样肯定不会出现这个问题了,但是不能有问题就重新初始啊

dm同步是用的乐观模式还是悲观模式?
悲观模式:等上游所有的分库分表ddl都到达后,在下游执行ddl
乐观模式:每个分库分表的ddl到达后就立马在下游tidb执行,可能有数据兼容的问题。