环境信息
canal 1.1.3 mysql 5.7
问题描述
mainTableDelete 方法逻辑问题, 既然是主表删除操作, 然后该方法又是通过查询sql语句后进行es数据操作, mysql的主表数据都已经删除了, 怎么可能sql语句得到结果呢?
原提问者GitHub用户violet250
如果主键是不带函数的单一字段,删除时不会通过sql反查数据。带函数或者复合主键暂不支持物理删除的同步
原回答者GitHub用户rewerma
根据您的描述,在Canal 1.1.3中使用ES进行数据同步时,发现主表数据已经被删除,但是Canal仍然尝试使用查询SQL语句进行ES数据操作,这导致了逻辑错误。
在Canal中,当主表的数据被删除时,Canal会调用"mainTableDelete"方法来进行相应的数据同步操作。在"mainTableDelete"方法中,Canal会执行查询SQL语句来获取ES中需要删除的数据,在执行完SQL语句后,Canal会将查询结果作为删除操作的参数,从而完成数据同步。
然而,在您的情况中,由于主表的数据已经被删除,查询SQL语句无法获取到任何结果。因此,Canal无法正确地进行数据同步,导致了逻辑错误。
为了解决这个问题,您可以尝试使用Canal的"row"模式进行数据同步。在"row"模式下,Canal会将每一行的数据解析成一个JSON对象,而不是按照列进行解析。这样,在主表数据被删除时,Canal仍然可以正确识别数据,并将其同步到目标系统中。
要使用"row"模式进行同步,您需要在Canal的配置文件中设置canal.instance.mode参数为"row"。例如:
canal.instance.mode=row 在这个例子中,我们使用"row"模式进行同步。这将使Canal将每一行的数据解析为一个JSON对象,并将其传输到目标系统中。
如果您希望继续使用Canal的默认模式进行同步,并且仍然要处理主表数据被删除的问题,建议您修改"mainTableDelete"方法的实现,以检查查询结果是否为空。如果查询结果为空,则可以将删除操作视为成功,从而跳过ES数据操作的逻辑。例如,您可以按照以下方式修改"mainTableDelete"方法的实现:
private void mainTableDelete(List pkList) { // 1. 构造查询SQL语句,获取需要删除的数据 String querySql = ... // 构造查询SQL语句 List<Map<String, String>> esDataList = ... // 执行SQL语句,获取查询结果
if (esDataList.isEmpty()) {
// 如果查询结果为空,跳过ES数据操作的逻辑
return;
}
// 2. 删除ES中的数据
for (Map<String, String> esData : esDataList) {
... // 执行ES数据操作,删除数据
}
} 在这个示例中,我们检查了查询结果是否为空。如果查询结果为空,则跳过ES数据操作的逻辑。这样,在主表数据被删除时,Canal仍然可以正确识别数据,并将其同步到目标系统中。
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。