-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
otter同步时,部分update的操作没有同步成功 #507
Comments
看你的意思是说,insert和update是同一批数据,otter处理时,insert和update语句合并成insert语句,但结果应该是update的数据吧,新人如不对,请见谅,参考下吧。 |
你说的是otter的入库算法,但目前现实的情况是,update的binlog没有执行,最后只有insert的数据。 |
我也发现了这个问题。看了下源码,应该是数据入库算法有问题。同一个事务里,如果先插入一条数据,再更新这条数据,数据入库合并时,并不能合并成一条insert事件,这样事实际执行时,insert事件和update事件分别在不同的线程里执行,update事件就有可能不起作用。 |
insert和update,会合并为一条insert去执行 |
@agapple insert和update会合并的话,那能提供些思路帮助我们排查这种问题吗?从现象上看是update的操作丢了,并且没有任何错误日志,没法下手排查这种问题。 |
@daemonluo 那你们是如何避免这种问题的?业务层自己把insert和update合成一个insert操作吗? |
@agapple 在同一批EventData中,insert和update的合并有个bug,RowKey这个对象在判断相等性和计算hashcode时,是直接调用EventColumn的相关方法,这样会把EventColumn的isUpdate属性计算进去,造成insert和update合并不成一个insert。 |
我这里也有这个问题,一段时间后,有一个表总条数是一样的,但某些数据有某些列的值不一样。估计是update没执行到。 |
有这个问题的都用的哪个版本 ?我不知道是不是最近换了4.2.15的问题。。以前4.2.13好像没有~ |
@daemonluo 看起来hashcode确实是
|
@luyee 我用的也是4.2.15 |
otter-4.2.14同样遇到这个状况@agapple ,这个有计划排查确认一下吗。 |
otter-4.2.16也有这种情况 有没有哪个版本没有这个问题呢 |
代码没有全部看完,发现一个问题, } else if (eventType.isUpdate()) {
// 获取变更前的主键.
for (Column column : beforeColumns) {
if (isKey(tableHolder, tableName, column)) {
oldKeyColumns.put(column.getName(), copyEventColumn(column, true, tableHolder));
// 同时记录一下new
// key,因为mysql5.6之后出现了minimal模式,after里会没有主键信息,需要在before记录中找
keyColumns.put(column.getName(), copyEventColumn(column, true, tableHolder));
} else {
if (needAllColumns && entry.getHeader().getSourceType() == CanalEntry.Type.ORACLE) {
// 针对行记录同步时,针对oracle记录一下非主键的字段,因为update时针对未变更的字段在aftercolume里没有
notKeyColumns.put(column.getName(), copyEventColumn(column, isRowMode, tableHolder));
}
}
} if (!keyColumns.isEmpty()) {
eventData.setKeys(keys);
if (eventData.getEventType().isUpdate() && !oldKeys.equals(keys)) { // update类型,如果存在主键不同,则记录下old
// keys为变更前的主键
eventData.setOldKeys(oldKeys);
} 但是在DbLoadMerger中打印日志发现 keys和oldkeys是一样的(isupdate 为 false),这不和逻辑 List<EventColumn> tnewPks = new ArrayList<EventColumn>();
List<EventColumn> toldPks = new ArrayList<EventColumn>();
for (int i = 0; i < pks.size(); i++) {
EventColumn newPk = pks.get(i);
EventColumn oldPk = oldPks.get(i);
// 转化new pk
EventColumn tnewPk = translateColumn(data, newPk, tableHolder, dataMediaPair, translateColumnNames);
if (tnewPk != null) {
tnewPks.add(tnewPk);
// 转化old pk,这里不能再用translateColumnNames了,因为转化new
// pk已经remove过一次view name了
toldPks.add(translateColumn(tnewPk, oldPk.getColumnValue(), dataMediaPair));
}
} 再次将oldkeys的 |
@kitdine isUpdate 正确的值应该 当前值isUpdate=false old值 isUpdate=true 所有才会导致EventColumn的hashcode 不一致 |
各位大佬最后需改RowKey 吗 update应该可以解决 别的会不会有影响 还没看完源码 |
@yuyid 差不多就是RowKey跟EventColumn,可以参考下 记一次Otter中update bug |
@luyee 是的 这些都看过 我现在就是要评估这个改对 别的会不会有影响 |
@yuyid 同担心 所以暂时单独给rowkey写了个相关的hashcode()~ EventColumn原来的的保留没动 |
@luyee 单独维护fix这个bug版的otter么?不知道官方什么时候会修复这个bug, 生产环境影响太大了。 |
@agapple @daemonluo @luyee @victorqian 修改后 已经测试过insert +update merge成了一条insert (这个改动目前看不会影响别的) |
我看一下这个问题 |
修改的思路:将pk的isUpdate设置为true,因为pk的update有内置的逻辑来处理. 当时调整应该是为DRDS做的一个变更导致 |
感谢agapple解决了我们大问题
| |
7
邮箱:pjobmail@163.com
|
Signature is customized by Netease Mail Master
在2018年08月01日 15:48,agapple 写道:
修改的思路:将pk的isUpdate设置为true,因为pk的update有内置的逻辑来处理. 当时调整应该是为DRDS做的一个变更导致
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.
|
8月份会发布一个修复版本 |
v4.2.16-alpha 2,打包了一个版本 |
请问你们是怎么模拟出来的,我怎么模拟不出来insert+update不合并的情况。 otter版本4.2.13 |
大神们,我使用4.2.16版本,发现在一个事务中,先insert后再update 100条记录,会有1-2十条数据update没成功,也没有错误,这个要怎么解决呢? |
有一种场景,业务上先insert一条数据,再update这条数据。otter进行同步时,update的这个操作丢失了,日志中也没有报错信息。是node在消费时因为多线程原因导致先操作了update失败,然后insert了数据吗?
The text was updated successfully, but these errors were encountered: