首页 > 其他 > 详细

Otter 同步出现时间列上值不一致问题

时间:2021-03-14 00:23:06      阅读:90      评论:0      收藏:0      [点我收藏+]

                                         Otter 同步出现时间列上值不一致问题

 

 

背景:

由于历史原因我们DB中引入了多源复制技术,在之后的使用过程中发现了一些弊端,于是准备去掉这套架构,使用otter来代替多源复制。在otter同步跑了很长一段时间之后,我们准备上线这套集群,却发现了一些不一致的情况。

 

问题:

之前otter使用的不是特别多,对其稳定性也不是很有信心,为了检验源库数据和目的数据的一致性,避免切换后出现数据不一致的问题,我们写脚本抽样比对了部分数据,结果发现两边的确存在数据不一致的情况,以下是其中一个案例。

源数据

< 2357 999999999 0 刘 2030420 罗 2409 红娘二部(易) 270 重庆解放碑店 2012218 陈 2020-05-18 02:27:04 2020-05-19 12:20:18 NULL 0 0 0 0 2020-05-19 12:20:18 2020-05-19 12:20:18

目的数据

> 2357 999999999 0 刘 2030420 罗 2409 红娘二部(易) 270 重庆解放碑店 2012218 陈 2020-05-18 02:27:04 2020-05-19 12:20:18 NULL 0 0 0 0 2020-05-19 12:20:18 2020-05-27 10:53:37

表结构

CREATE TABLE `ArchiveMeetDetail` (

  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 主键,

  `memberId` int(11) NOT NULL ,

  `sex` tinyint(3) NOT NULL ,

  `trueName` varchar(10) NOT NULL ,

  `belongWorkerId` int(11) NOT NULL ,

  `belongWorkerName` varchar(20) NOT NULL ,

  `belongGroupId` int(11) NOT NULL ,

  `belongGroupName` varchar(20) NOT NULL ,

  `belongDeptId` int(11) NOT NULL ,

  `belongDeptName` varchar(20) NOT NULL ,

  `workerId` int(11) NOT NULL ,

  `workerName` varchar(255) NOT NULL ,

  `archiveTime` datetime NOT NULL ,

  `archivePassTime` datetime NOT NULL ,

  `firstMeetTime` datetime DEFAULT NULL ,

  `meetThisMonth` int(11) NOT NULL DEFAULT 0 ,

  `miniMeetThisMonth` int(11) NOT NULL DEFAULT 0 ,

  `meetTotal` int(11) NOT NULL DEFAULT 0 ,

  `miniMeetTotal` int(11) NOT NULL DEFAULT 0 ,

  `createTime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ,

  `updateTime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ,

  PRIMARY KEY (`id`),

  KEY `idx_member_id` (`memberId`) USING BTREE,

  KEY `idx_group_id` (`belongGroupId`) USING BTREE,

  KEY `idx_dept_id` (`belongDeptId`) USING BTREE,

  KEY `idx_archive_pass_time` (`archivePassTime`) USING BTREE

) ENGINE=InnoDB AUTO_INCREMENT=3543 DEFAULT CHARSET=utf8 

我们发现:

1.都是这种updatetime时间列上的数据不一致。

2.updatetime列上有ON UPDATE CURRENT_TIMESTAMP 子句,也就是每次更新的时候这列的值会自动更新为当前时间。

 

排查:

首先我们在源库解析binlog,提取对这个表修改的sql,主要是两个sql,一个update语句和一个insert语句。

我们测试了update 语句在修改其他列或updatetime 列的情况,也测试了insert在指定updatetime值和不指定updatetime 值的情况(第一次可能测试的不是很仔细),结果都是源和目的的数据是完全一致的。

之后,根据目的数据的修改时间(2020-05-27 10:53:37),我们排查目的库的binlog,找到修改这条记录所对应的sql。

UPDATE `zhenai_crm_matchmaker`.`ArchiveMeetDetail` SET `firstMeetTime`=NULL, `updateTime`=2020-05-27 10:53:37, `miniMeetTotal`=0, `archiveTime`=2020-05-18 02:27:04, `belongDeptName`=重庆解放碑店, `workerId`=2012218, `createTime`=2020-05-19 12:20:18, `belongGroupId`=2409, `memberId`=999999999, `belongWorkerId`=2030420, `sex`=0, `belongGroupName`=红娘二部(易), `trueName`=, `belongWorkerName`=, `meetTotal`=0, `workerName`=, `miniMeetThisMonth`=0, `belongDeptId`=270, `meetThisMonth`=0, `id`=2357, `archivePassTime`=2020-05-19 12:20:18 WHERE `firstMeetTime` IS NULL AND `updateTime`=2020-05-19 12:20:18 AND `miniMeetTotal`=0 AND `archiveTime`=2020-05-18 02:27:04 AND `belongDeptName`=重庆解放碑店 AND `workerId`=2030420 AND `createTime`=2020-05-19 12:20:18 AND `belongGroupId`=2409 AND `memberId`=999999999 AND `belongWorkerId`=2030420 AND `sex`=0 AND `belongGroupName`=红娘二部(易) AND `trueName`= AND `belongWorkerName`= AND `meetTotal`=0 AND `workerName`= AND `miniMeetThisMonth`=0 AND `belongDeptId`=270 AND `meetThisMonth`=0 AND `id`=2357 AND `archivePassTime`=2020-05-19 12:20:18 LIMIT 1; #start 142683935 end 142684421 time 2020-05-27 10:53:37

如果目的库这个时间有修改,那么源库这个时间应该也是有同样的sql在执行,顺着这条思路,查查了源库binlog,解析出了对应的sql。

UPDATE `zhenai_crm_matchmaker`.`ArchiveMeetDetail` SET `firstMeetTime`=NULL, `updateTime`=2020-05-19 12:20:18, `miniMeetTotal`=0, `archiveTime`=2020-05-18 02:27:04, `belongDeptName`=重庆解放碑店, `workerId`=2012218, `createTime`=2020-05-19 12:20:18, `belongGroupId`=2409, `memberId`=999999999, `belongWorkerId`=2030420, `sex`=0, `belongGroupName`=红娘二部(易), `trueName`=, `belongWorkerName`=, `meetTotal`=0, `workerName`=, `miniMeetThisMonth`=0, `belongDeptId`=270, `meetThisMonth`=0, `id`=2357, `archivePassTime`=2020-05-19 12:20:18 WHERE `firstMeetTime` IS NULL AND `updateTime`=2020-05-19 12:20:18 AND `miniMeetTotal`=0 AND `archiveTime`=2020-05-18 02:27:04 AND `belongDeptName`=重庆解放碑店 AND `workerId`=2030420 AND `createTime`=2020-05-19 12:20:18 AND `belongGroupId`=2409 AND `memberId`=999999999 AND `belongWorkerId`=2030420 AND `sex`=0 AND `belongGroupName`=红娘二部(易) AND `trueName`= AND `belongWorkerName`= AND `meetTotal`=0 AND `workerName`= AND `miniMeetThisMonth`=0 AND `belongDeptId`=270 AND `meetThisMonth`=0 AND `id`=2357 AND `archivePassTime`=2020-05-19 12:20:18 LIMIT 1; #start 126420599 end 126421098 time 2020-05-27 10:53:37

单看每一边的binlog及表的数据,都没有什么问题,binlog和数据都是对应的。但问题是同步过去为什么数据不一样,当然是因为执行的sql不一样。可是执行的sql为什么不一样呢?难道同步过去binlog不一样。但是这不可能的,主库和从库的binlog应该是一样的,

那这里目的库的updatetime值为什么跟主库不一样呢?仔细看,就可以发现两点:

1.源库在修改这条数据的时候也修改了updatetime 的值,但不是修改成最新的时间,而是跟原来一样的时间。

2.而目的库,updatetime则是较新的一个值,很可能是当时执行时的时间。

基于以上两点我们又做了测试,终于发现了问题。

 

 

验证:

 

测试SQL

结果

1

update set updatetime = ‘2020-05-19 12:20:18‘ , workerName = ‘test‘ ...

两边数据不一致

2

update set updatetime = ‘2020-05-28 10:00:00‘ , workerName = ‘test‘ ...

两边数据一致

我们发现出现不一致要有两个条件,

第一,updatetime的值要修改成跟原来一样,也就是updatetime的值要保持不变,

第二,除了updatetime列外,还需要变更其他列的数据。

对于源库来说,它在执行update的时候把updatetime列的值修改成跟原来一样的值(如果不这么做,那么updatetime的值就会是执行时的时间)。而binlog传到目的端,在解析binog的时候,(由于一些参数)otter会根据列的变更来同步数据,而updatetime这列修改前的时间和修改后的时间是一样的,otter就没有同步这列,比如第一个sql,otter解析执行的sql可能是这个样子的:update set workerName = ‘test‘ ... 。由于updatetime这列是自动更新的,所以实际是这样的:update set updatetime = ‘#current_time#‘ ,workerName = ‘test‘ ... 。这就导致了目的时间是当前时间,和源库的时间不一样。

 

解决:

查询资料及官方文档,我们找到了otter中的一个可能造成这种结果的参数--channel 中的同步模式,有两种同步模式:
行模式 ,兼容otter3的处理方案,改变记录中的任何一个字段,触发整行记录的数据同步,在目标库执行merge sql。

列模式 ,基于log中的具体变更字段,按需同步。

原先我们设置的是列模式,对于一般情况,同步不会有问题,但无法处理上面这种特殊情况下的同步。改为行模式后,经测试,两边的数据一致。

 

Otter 同步出现时间列上值不一致问题

原文:https://www.cnblogs.com/ayard/p/14530571.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!