[FAQ] DM 报错 handle a potential duplicate event event from x in xx diff from passed-in event

[问题澄清]

DM 同步过程中报错:

handle a potential duplicate event \u0026{Timestamp:1591553976 EventType:DeleteRowsEventV2 ServerID:11 EventSize:7696 LogPos:9440 Flags:0} in mysql-bin.004963: check event \u0026{Timestamp:1591553976 EventType:DeleteRowsEventV2 ServerID:11 EventSize:7696 LogPos:9440 Flags:0} whether duplicate in /data/dm/deploy/relay_log/89b73e86-22ad-11e9-81b6-70c7f218fe45.000001/mysql-bin.004963: event from 1744 in /data/dm/deploy/relay_log/89b73e86-22ad-11e9-81b6-70c7f218fe45.000001/mysql-bin.004963 diff from passed-in event

[原因分析]

在 DM 进行 relay log 拉取与增量同步过程中,如果遇到了上游超过 4GB 的 binlog 文件,就可能出现这两个错误。

原因是 DM 在写 relay log 时需要依据 binlog position 及文件大小对 event 进行验证,且需要保存同步的 binlog position 信息作为 checkpoint。但是 MySQL binlog position 官方定义使用 uint32 存储,所以超过 4G 部分的 binlog position 的 offset 值会溢出,进而出现上面的错误

[解决方案]

对于 relay 处理单元,可通过以下步骤手动恢复:

  1. 在上游确认出错时对应的 binlog 文件的大小超出了 4GB。
  2. 停止 DM-worker。
  3. 将上游对应的 binlog 文件复制到 relay log 目录作为 relay log 文件。
  4. 更新 relay log 目录内对应的 relay.meta 文件以从下一个 binlog 开始拉取。如果 DM worker 已开启 enable_gtid ,那么在修改 relay.meta 文件时,同样需要修改下一个 binlog 对应的 GTID。如果未开启 enable_gtid 则无需修改 GTID。例如:报错时有 binlog-name = "mysql-bin.004451"binlog-pos = 2453 ,则将其分别更新为 binlog-name = "mysql-bin.004452"binlog-pos = 4 ,同时更新 binlog-gtid = "f0e914ef-54cf-11e7-813d-6c92bf2fa791:1-138218058"
  5. 重启 DM-worker。

对于 binlog replication 处理单元,可通过以下步骤手动恢复:

  1. 在上游确认出错时对应的 binlog 文件的大小超出了 4GB。
  2. 通过 stop-task 停止同步任务。
  3. 将下游 dm_meta 数据库中 global checkpoint 与每个 table 的 checkpoint 中的 binlog_name 更新为出错的 binlog 文件,将 binlog_pos 更新为已同步过的一个合法的 position 值,比如 4。例如:出错任务名为 dm_test ,对应的 source-idreplica-1 ,出错时对应的 binlog 文件为 mysql-bin|000001.004451 ,则执行 UPDATE dm_test_syncer_checkpoint SET binlog_name='mysql-bin|000001.004451', binlog_pos = 4 WHERE id='replica-1';
  4. 在同步任务配置中为 syncers 部分设置 safe-mode: true 以保证可重入执行。
  5. 通过 start-task 启动同步任务。
  6. 通过 query-status 观察同步任务状态,当原造成出错的 relay log 文件同步完成后,即可还原 safe-mode 为原始值并重启同步任务。

[参考案例]

[参考文档]