【Java】Elastic canal数据同步到ES配置常见报错

InterviewCoder

# 【Java】Elastic canal 数据同步到 ES 配置常见报错

# 0. 引言

所有报错均为博主在实操过程中遇到的错误和解决办法,如果有其他报错或者不同的解决办法,请留言告诉我

安装 canal 过程中遇到问题,先在本文中查询是否有相同报错,将会为你节约大量排错时间

# 环境

1
2
3
4
jdk1.8
canal 1.1.5
mysql8.0
es7.13.0

# 1. Unknown system variable ‘query_cache_size’

这是因为 mysql 驱动包的版本过低导致的,query cache 在 MySQL5.7.20 就已经过时了,而在 MySQL8.0 之后就已经被移除了

1、只需要将 lib 中的驱动器替换成 mysql-connector-java-8.0.22.jar

2、修改驱动器权限

1
2
chmod 777 lib/mysql-connector-java-8.0.22.jar
chmod +st lib/mysql-connector-java-8.0.22.jar

查看权限如图所示

1
ll lib

在这里插入图片描述

# 2. Reason: No converter found capable of converting from type [java.lang.String] to type [java.util.Map<java.lang.String, java.lang.String>]

启动 canal-adapter 报错:

1
2
3
Failed to bind properties under 'canal.conf.canal-adapters[0].groups[0].outer-adapters[1].properties' to java.util.Map<java.lang.String, java.lang.String>:

Reason: No converter found capable of converting from type [java.lang.String] to type [java.util.Map<java.lang.String, java.lang.String>]

解决:
观察报错信息可以得知是配置文件中的 outer2(0 基,所以 outer-adapter [1] 实际指的是 2)的 properties 配置有问题,我们观察配置文件,发现是 properties 下的 mode,cluster.name 等属性与 properties 同级了,将其如下图所示后退两字符即可。
配置

# 3. RuntimeException: java.lang.RuntimeException: No data source found: xxxx

这个因为在 conf/es/xxx.yml 中配置的 dataSourceKey 并没有在 conf/application.yml 中的 srcDataSources 中维护

如下图所示,es 中的 dataSourceKey 需要在 applicaiton.yml 中设置,默认是 defaultDS
在这里插入图片描述
在这里插入图片描述

# 4. Reason: Unable to set value for property src-data-sources

1
2
3
Failed to bind properties under 'canal.conf' to com.alibaba.otter.canal.adapter.launcher.config.AdapterCanalConfig:

Reason: Unable to set value for property src-data-sources

原因一:
mysql 驱动器导致的问题,使用的数据库是 8.x。驱动器是 5.x 的,将 mysql 驱动替换为 8.0.x 版本的。如上所示报错 1

原因二:
检查该报错前的日志,是否有其他相关报错信息,比如无相关数据库,如下所示,根据其报错内容来检查配置项并且调整即可
在这里插入图片描述

# 5. java.sql.SQLException: null, message from server: “Host ‘172.16.188.2’ is blocked because of many connection errors; unblock with ‘mysqladmin flush-hosts’”

同一个 ip 在短时间内产生太多中断的数据库连接而导致的阻塞

登录对应的 mysql,执行如下指令

1
flush hosts;

# 6. IllegalStateException: Extension instance(name: es7, class: interface com.alibaba.otter.canal.client.adapter.OuterAdapter) could not be instantiated: class could not be found

一般 could not be instantiated: class could not be found 这样的报错是配置文件的问题,如上的报错可以看到是 name: es7 中的错误,在官方的示例文档中使用的是 name: es6 # or es7

在 canal1.1.5 + 版本中设置的是 name: es6 # 或者 es7

但在 1.1.4 版本中直接使用 name: es 即可

# 7. IllegalArgumentException: Not found the mapping info of index: user

1、这个报错是 ES 的 mapping 设置的问题,确保 es 中有该索引,并且确认是否有部分字段没有在 es 中设置 mapping, 这个要对应之前设置的 sql,以及 es 中的 mappings 来解决

2、使用了 elasticsearch 7.x,但 adapter1.1.4 默认支持 es6.x
解决方案:
(1)修改 adapter 源码,将 es 依赖调整为 7.x;参考博客 adapter1.1.4 修改源码支持 es7.x
(2)换成 adapter1.1.5

# 8. IllegalArgumentException: Illegal character in scheme name at index 0: 172.16.188.7:9200

如果连接 es 使用的是 rest 方式,那么 hosts 中的 ip 前要添加 http:// ,如

1
hosts: http://172.16.188.7:9200

# 9. com.alibaba.druid.pool.DruidDataSource cannot be cast to com.alibaba.druid.pool.DruidDataSource

1
2
3
4
5
6
7
8
9
java.lang.RuntimeException: java.lang.RuntimeException: java.lang.ClassCastException: com.alibaba.druid.pool.DruidDataSource cannot be cast to com.alibaba.druid.pool.DruidDataSource
at com.alibaba.otter.canal.client.adapter.es7x.ES7xAdapter.init(ES7xAdapter.java:54) ~[client-adapter.es7x-1.1.5-jar-with-dependencies.jar:na]
at com.alibaba.otter.canal.adapter.launcher.loader.CanalAdapterLoader.loadAdapter(CanalAdapterLoader.java:225) [client-adapter.launcher-1.1.5.jar:na]
at com.alibaba.otter.canal.adapter.launcher.loader.CanalAdapterLoader.init(CanalAdapterLoader.java:56) [client-adapter.launcher-1.1.5.jar:na]
at com.alibaba.otter.canal.adapter.launcher.loader.CanalAdapterService.init(CanalAdapterService.java:60) [client-adapter.launcher-1.1.5.jar:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_271]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_271]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_271]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_271]

原因:
druid 包冲突
解决:
1、修改 client-adapter/escore/pom.xml

1
2
3
4
5
6
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<!--add by whx 20220112-->
<scope>provided</scope>
</dependency>

2、重新打包
在这里插入图片描述
3、将 client-adapter/es7x/target/client-adapter.es7x-1.1.5-jar-with-dependencies.jar 上传到服务器,替换 adataper/plugin 下的同名 jar 文件
在这里插入图片描述

1
scp client-adapter.es7x-1.1.5-jar-with-dependencies.jar root@172.16.188.2:/var/local

4、给该文件赋权

1
chmod 777 /var/local/client-adapter.es7x-1.1.5-jar-with-dependencies.jar 

5、重启服务

# 10 CanalParseException: java.io.IOException: EOF encountered

将 lib 目录下的 mysql 驱动器替换为 mysql8.0,并附权。参考上述

# 11. CanalClientException: java.io.IOException: Broken pipe Error sync but ACK

服务连接断开了,将 deployer 和 adapter 都关闭,先启动 deployer 再启动 adapter

# 12. DocumentMissingException[[_doc][1413298413755211778]: document missing]

1、es 集群出现问题,导致 doc 无法分配。常见的是分片数的问题,可能是副本分片过多,导致集群报黄
解决:
因为我的是 es 单节点,所以将主分片数设置为 1,副本分片设置为 0。不申明的话默认创建副本分片数为 1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
PUT user
{
"mappings": {
"properties": {
"code": {
"type": "keyword"
},
"email": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword"
}
}
},
"realName": {
"type": "text",
"analyzer": "ik_smart",
"fields": {
"keyword": {
"type": "keyword"
}
}
},
"roleId": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword"
}
}
},
"postId": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword"
}
}
},
"deptId": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword"
}
}
}
}
},
"settings": {
"number_of_replicas": 0,
"number_of_shards": 1
}
}

2、修改的 mysql 数据库数据,在 es 中不存在。先进行全量同步,再进行增量同步

在 conf/example/instance.properties 中修改

1
2
3
4
5
# 全量同步
canal.instance.master.journal.name=mysql-bin.000001
canal.instance.master.position=0
#2019-01-01 00:00:00 上一次更新的时间
canal.instance.master.timestamp=1546272000000

# 13. ERROR c.a.otter.canal.server.netty.handler.SessionHandler - something goes wrong with channel:[id: 0x23d9cad9, /127.0.0.1:46472 :> /127.0.0.1:11111], exception=java.nio.channels.ClosedChannelException

这是由于 deployer 中的 conf/example/meta.dat 与 instance.properties 文件中的 journalName,position,timestamp 不一致导致的

1
2
3
4
5
6
7
# 查询bin log位置
show master status;
# 如果显示的binlog不为000001可以执行以下语句重置binlog(轻易别操作,最好让专业的运维人员操作)
# 该操作会重新生成binlog,之前的binlog就会清空,之前的数据就不会再同步
reset master;
# 刷新log日志,自此刻开始产生一个新编号的binlog日志文件
flush logs;

在这里插入图片描述
将 meta.dat 删除或者修改一致即可。删除后将会按照 instance.properties 中设置的起点同步,生产环境考虑好需要后再删除。

如果想要将之前的数据也同步的话,可以将数据库先导出,再重新导入一遍,即可重新生成 binlog,实现数据的全量同步

# 14. Received error packet: errno = 1236, sqlstate = HY000 errmsg = Could not find first log file name in binary log index file

mysql bin log 数据不同步,刷新一下即可

1
flush logs;

# 15. binlog 也设置为 000001 了,timestamp 也设置了,但就是无法实现全量同步

1、删除 conf/example/meta.dat
2、调整 conf/example/instance.properties

1
2
3
4
canal.instance.master.journal.name=mysql-bin.000001
canal.instance.master.position=0
#2019-01-01 00:00:00 上一次更新的时间
canal.instance.master.timestamp=1546272000000

3、重启 deployer

另外需要注意的是如果 bin log 是只会记录增量操作的,也就是说开启 bin log 之前的历史数据是不会记录的,如果需要同步者之前的数据,解决这个问题有三个办法:
(1)通过 logstash-input-jdbc 来实现
(2)通过业务代码来实现(后续会详细讲解这两种方式,可以关注我后续的博客)
(3)复制原数据库数据到开启了 binlog 的从数据库,然后从从数据库同步

# 16. adapter 启动报错:something goes wrong when starting up the canal client adapters: java.lang.NullPointerException: null

这个报错是空指针报错,很明显是哪里获取为空的,这种错误没有固定的原因,但大概率上可以锁定配置文件的问题

1、adapter 的配置文件中是有包含了 mysql、es、mq、zk 等配置,如果不需要的配置项,就将其注释掉,不要打开

比如我这里的报错原因就是因为打开了 zookeeperHosts,但是没有配置具体值,所以导致了空指针,因为我不需要 zk,将其注释掉即可

1
2
# flatMessage: true
# zookeeperHosts:

2、某些必要的配置没有设置,快速排查的方式就是根据官方文档中给出的配置文件对比排错
可以参考如下配置文件

3、配置文件中配置项排版错位

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
server:
port: 8081
spring:
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
default-property-inclusion: non_null

canal.conf:
mode: tcp #tcp kafka rocketMQ rabbitMQ
flatMessage: true
zookeeperHosts:
syncBatchSize: 1000
retries: 0
timeout:
accessKey:
secretKey:
consumerProperties:
# canal tcp consumer
canal.tcp.server.host: 127.0.0.1:11111
canal.tcp.zookeeper.hosts:
canal.tcp.batch.size: 500
canal.tcp.username:
canal.tcp.password:
# kafka consumer
kafka.bootstrap.servers: 127.0.0.1:9092
kafka.enable.auto.commit: false
kafka.auto.commit.interval.ms: 1000
kafka.auto.offset.reset: latest
kafka.request.timeout.ms: 40000
kafka.session.timeout.ms: 30000
kafka.isolation.level: read_committed
kafka.max.poll.records: 1000
# rocketMQ consumer
rocketmq.namespace:
rocketmq.namesrv.addr: 127.0.0.1:9876
rocketmq.batch.size: 1000
rocketmq.enable.message.trace: false
rocketmq.customized.trace.topic:
rocketmq.access.channel:
rocketmq.subscribe.filter:
# rabbitMQ consumer
rabbitmq.host:
rabbitmq.virtual.host:
rabbitmq.username:
rabbitmq.password:
rabbitmq.resource.ownerId:
srcDataSources:
defaultDS:
url: jdbc:mysql://172.16.188.1:3306/bladex?useUnicode=true
#driverClassName: com.mysql.cj.jdbc.Driver
username: root
password: 123456
canalAdapters:
- instance: example # canal instance Name or mq topic name
groups:
- groupId: g1
outerAdapters:
- name: logger
-
key: esKey
name: es7 # es6 or es7
hosts: http://172.16.188.7:9200 # 集群地址,逗号隔开. 127.0.0.1:9200 for rest mode or 127.0.0.1:9300 for transport mode
properties:
mode: rest # rest or transport
# security.auth: test:123456 # only used for rest mode
cluster.name: cluster1

# 17 Field error in object ‘target’ on field ‘esMapping’: rejected value [];

1
2
3
4
5
6
7
Field error in object 'target' on field 'esMapping': rejected value []; codes 
[typeMismatch.target.esMapping,typeMismatch.esMapping,typeMismatch.com.alibaba.otter.canal.client.adapter.es.core.config.ESSyncConfig$ESMapping,typeMismatch];
arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [target.esMapping,esMapping]; arguments []; default message [esMapping]]; default message [Failed to convert property value of type 'java.lang.String' to required type
'com.alibaba.otter.canal.client.adapter.es.core.config.ESSyncConfig$ESMapping' for property 'esMapping'; nested
exception is java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String' to required type
'com.alibaba.otter.canal.client.adapter.es.core.config.ESSyncConfig$ESMapping' for property 'esMapping': no
matching editors or conversion strategy found]

这是配置文件问题,检查 es 下的配置 yml 文件,特别是 sql 语句的语法是否有问题

# 18 java.util.NoSuchElementException

没有找到对应字段导致

检查下 canal 配置文件中的字段是否在 es mapping 中有对应的,大小写是否一致,是否有遗漏

因为我的操作是 mysql 同步至 es,所以这里说明几项容易出错的地方:
1、canal 配置文件中的 sql 中是否大小写一致,canal 是区分大小写的
2、sql 中设置的别名是否与 es mappings 中的名称一致,允许 es 中的部分字段为空,但是不允许 sql 中查询出来的字段在 es mappings 中找不到对应的字段
3、canal 配置文件中的 dataSourceKey 是否正确,其对应到 canal application.yml 配置文件中的数据库是否正确

1
dataSourceKey: aaa

application.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
srcDataSources:
aaa: # 与之对应
url: jdbc:mysql://192.168.244.1:3306/aaa?useUnicode=true
#driverClassName: com.mysql.cj.jdbc.Driver
username: root
password: 123456
xxx:
url: jdbc:mysql://192.168.244.1:3306/xxx?useUnicode=true
username: root
password: 123456
yyy:
url: jdbc:mysql://192.168.244.1:3306/yyy?useUnicode=true
username: root
password: 123456

4、canal 配置文件中的排版是否正确,特别注意_index,_type 等属性要放在 esMappings 下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
dataSourceKey: aaa # 这里的key与上述application.yml中配置的数据源保持一致
outerAdapterKey: esKey # 与上述application.yml中配置的outerAdapters.key一直
destination: example # 默认为example,与application.yml中配置的instance保持一致
groupId:
esMapping:
_index: dept
_type: _doc
_id: _id
sql: "select
t.id,
t.id as _id,
t.dept_name as deptName,
t.dept_category as deptCategory,
t.parent_id as parentId,
t.ancestors as ancestors,
t.third_party_id as thirdPartyId,
t.phone as phone,
t.address as address,
t.is_deleted as isDeleted
from
dept t"
#etlCondition: "where t.update_time>='{0}'"
commitBatch: 3000

5、sql 查询出来的字段类型与 es mappings 中的字段数据类型是否一致

6、多表同步到同一个索引时,如果都有同一个常量列且值不同时会报错。
如下所示的两个配置文件都有 userSource 常量列用于区分不同的数据来源,但是如下的配置会报错。
xxx.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
dataSourceKey: aaa # 这里的key与上述application.yml中配置的数据源保持一致
outerAdapterKey: esKey # 与上述application.yml中配置的outerAdapters.key一直
destination: example # 默认为example,与application.yml中配置的instance保持一致
groupId:
esMapping:
_index: user
_type: _doc
_id: _id
sql: "select
t.id,
0 as userSource,
from
user t"
commitBatch: 3000

yyy.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
dataSourceKey: aaa # 这里的key与上述application.yml中配置的数据源保持一致
outerAdapterKey: esKey # 与上述application.yml中配置的outerAdapters.key一直
destination: example # 默认为example,与application.yml中配置的instance保持一致
groupId:
esMapping:
_index: user
_type: _doc
_id: _id
sql: "select
t.id,
1 as userSource,
from
user_wx t"
commitBatch: 3000

# 19. adapter 日志中没有报错,但是没有读取 binlog | Could not find first log file name in binary log index file

adapter 日志中没有报错信息,于是去查看 deployer 日志,这里的 example 是你配置的实例

1
cat logs/example/example.log

会发现报错:

1
Could not find first log file name in binary log index file

解决:
1、既然问题是没有找到数据库的 binglog 文件位置,那么就查看一下现在的 binlog 文件位置,登陆 mysql 执行

2.1 如果你是做增量同步,那么查询当前 binlog 位置

1
show master status;

在这里插入图片描述
修改 conf/example/instance.properties 文件

1
2
3
4
5
6
canal.instance.master.address=192.168.244.17:3306
# 这里的文件名要与上面的保持一致,我这里就是文件名不一致,写成了mysql-bin.000001
canal.instance.master.journal.name=binlog.000003
canal.instance.master.position=5921
canal.instance.master.timestamp=
canal.instance.master.gtid=

2.2 如果你要做全量同步,查询 binlog 文件

1
show binary logs;

在这里插入图片描述

1
2
3
4
5
6
7
canal.instance.master.address=192.168.244.17:3306
# 这里的文件名要与上面的保持一致,我这里就是文件名不一致,写成了mysql-bin.000001
canal.instance.master.journal.name=binlog.000001
# 位置从0开始
canal.instance.master.position=0
canal.instance.master.timestamp=
canal.instance.master.gtid=

3、重启 deployer 和 adapter

# 20. ERROR c.a.otter.canal.adapter.launcher.loader.AdapterProcessor - java.lang.NullPointerException

启动 adapter 报错:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2022-05-21 06:28:44.444 [pool-2-thread-1] ERROR c.a.otter.canal.adapter.launcher.loader.AdapterProcessor - java.lang.NullPointerException
java.lang.RuntimeException: java.lang.NullPointerException
at com.alibaba.otter.canal.client.adapter.es.core.service.ESSyncService.sync(ESSyncService.java:116) ~[na:na]
at com.alibaba.otter.canal.client.adapter.es.core.service.ESSyncService.sync(ESSyncService.java:64) ~[na:na]
at com.alibaba.otter.canal.client.adapter.es.core.ESAdapter.sync(ESAdapter.java:115) ~[na:na]
at com.alibaba.otter.canal.client.adapter.es.core.ESAdapter.sync(ESAdapter.java:94) ~[na:na]
at com.alibaba.otter.canal.adapter.launcher.loader.AdapterProcessor.batchSync(AdapterProcessor.java:139) ~[client-adapter.launcher-1.1.5.jar:na]
at com.alibaba.otter.canal.adapter.launcher.loader.AdapterProcessor.lambda$null$1(AdapterProcessor.java:97) ~[client-adapter.launcher-1.1.5.jar:na]
at java.util.concurrent.CopyOnWriteArrayList.forEach(CopyOnWriteArrayList.java:895) ~[na:1.8.0_312]
at com.alibaba.otter.canal.adapter.launcher.loader.AdapterProcessor.lambda$null$2(AdapterProcessor.java:94) ~[client-adapter.launcher-1.1.5.jar:na]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[na:1.8.0_312]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[na:1.8.0_312]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[na:1.8.0_312]
at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_312]
Caused by: java.lang.NullPointerException: null
at com.alibaba.otter.canal.client.adapter.es7x.support.ES7xTemplate.insert(ES7xTemplate.java:79) ~[na:na]
at com.alibaba.otter.canal.client.adapter.es.core.service.ESSyncService.singleTableSimpleFiledInsert(ESSyncService.java:448) ~[na:na]
at com.alibaba.otter.canal.client.adapter.es.core.service.ESSyncService.insert(ESSyncService.java:139) ~[na:na]
at com.alibaba.otter.canal.client.adapter.es.core.service.ESSyncService.sync(ESSyncService.java:99) ~[na:na]
... 11 common frames omitted
2022-05-21 06:28:44.449 [Thread-4] ERROR c.a.otter.canal.adapter.launcher.loader.AdapterProcessor - Outer adapter sync failed! Error sync but ACK!

解决:
1、修改 adapter/application.yml,给 outerAdapters 配置一个 key,注意这里如果有多个 adapter 实例,那么就配置不同的 key

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
canalAdapters:
- instance: test # canal instance Name or mq topic name
groups:
- groupId: g2
outerAdapters:
# - name: logger
-
key: esKey3 # 配置key
name: es7 # es6 or es7
#hosts: http://192.168.101.11:9200 # 集群地址,逗号隔开. 127.0.0.1:9200 for rest mode or 127.0.0.1:9300 for transport mode
hosts: http://192.168.244.11:9200 # 集群地址,逗号隔开. 127.0.0.1:9200 for rest mode or 127.0.0.1:9300 for transport mode
properties:
mode: rest # rest or transport
security.auth: elastic:elastic # only used for rest mode
cluster.name: blade-cluster

# 21. CanalParseException: parse row data failed. | column size is not match for table

deployser 日志报错:

1
2
3
4
5
2022-05-21 07:45:15.651 [MultiStageCoprocessor-Parser-fleet-0] ERROR com.alibaba.otter.canal.common.utils.NamedThreadFactory - from MultiStageCoprocessor-Parser-fleet-0
com.alibaba.otter.canal.parse.exception.CanalParseException: com.alibaba.otter.canal.parse.exception.CanalParseException: com.alibaba.otter.canal.parse.exception.CanalParseException: parse row data failed.
Caused by: com.alibaba.otter.canal.parse.exception.CanalParseException: com.alibaba.otter.canal.parse.exception.CanalParseException: parse row data failed.
Caused by: com.alibaba.otter.canal.parse.exception.CanalParseException: parse row data failed.
Caused by: com.alibaba.otter.canal.parse.exception.CanalParseException: column size is not match for table:fleet.source_project_cargo,9 vs 8

解决:
1、可以看到报错中已经给出明确提示了

1
column size is not match for table:fleet.source_project_cargo,9 vs 8

2、该错误官方中有解释
官方文档 TableMetaTSDB
在 instance.properties 中设置

1
2
3
4
5
6
7
8
9
canal.instance.tsdb.spring.xml=classpath:spring/tsdb/h2-tsdb.xml
# table meta tsdb info
canal.instance.tsdb.enable=true
# 以下配置不用开启,因为在canal.properties中已经设置过了,只要没有手动关闭过就不用再配置了
#canal.instance.tsdb.dir=${canal.file.data.dir:../conf}/${canal.instance.destination:}
#canal.instance.tsdb.url=jdbc:h2:${canal.instance.tsdb.dir}/h2;CACHE_SIZE=1000;MODE=MYSQL;
#canal.instance.tsdb.url=jdbc:mysql://127.0.0.1:3306/canal_tsdb
#canal.instance.tsdb.dbUsername=canal
#canal.instance.tsdb.dbPassword=canal

3、一般将这个开启就解决了,但是我这里即时将其开启还是报错,查阅相关资料有说将 canal.instance.tsdb.enable 设置为 false 后重启解决的,但是我这里将其设置为 false 后依旧没有解决

实在没有其他办法了,查阅官方 github,导致这个问题发生的原因是因为表结构发生过变化,但是 binlog 中读取到的与现在的表结构不一致导致。

于是直接跳过该 binlog checkpoint,也就是将 binlog 的读取位置设置为当前的最新 binlog 位置

(1)查阅当前 binlog 最新位置,mysql 中执行

1
show master status;

在这里插入图片描述
(2)将读取位置该为最新,修改 deployer conf/example/instance.properties

1
2
3
4
5
6
canal.instance.master.address=162.14.99.4:3306
canal.instance.master.journal.name=mysql-bin.000002
canal.instance.master.position=226586328
# 当前时间的时间戳形式
canal.instance.master.timestamp=1653140932
canal.instance.master.gtid=

(3)重启 deployer , adapter
(4)因为读取的是最新的 binlog。为了把当前的数据同步进来,将需要同步的表或库导出,然后再导入一遍。问题解决(注意:这里的解决方案要谨慎,生产环境因为时时刻刻在产生数据,可行性很低,所以看要么设置一个停机维护来进行实操)

# 22. use gtid and TableMeta TSDB should be config timestamp > 0

在 instance.properties 中设置时间戳

1
canal.instance.master.timestamp=1546272000000

# 23. RuntimeException: com.alibaba.fastjson.JSONException: unclosed string

该错误是因为 sql 中使用了 group_concat 函数,但是该函数默认长度是 1024,超过的会被截取,导致出现了 json 格式的数据格式不正确,没有正确的关闭 json

解决:
1、修改 my.cnf,扩大 group_concat_max_len

1
group_concat_max_len = 102400

2、重启 mysql

# 24. MySQLSyntaxErrorException: Unknown column ‘_v._id’ in ‘where clause’

sql 中没有 _id 字段导致,使用 as 将 id 命名别名: select id as _id

# 25. adapter 中有同步日志打印,但 es 中数据未同步

我这里出现这个问题是在 canal1.1.6 版本中,原因是 es7 文件夹中的 .yml 文件中书写的 sql 里使用了 `` 将表名括起来,导致未识别,如下所示

1
select id,name,age from `user`

解决:
将 `` 去掉即可

# 关于我

Brath 是一个热爱技术的 Java 程序猿,公众号「InterviewCoder」定期分享有趣有料的精品原创文章!

InterviewCoder

非常感谢各位人才能看到这里,原创不易,文章如果有帮助可以关注、点赞、分享或评论,这都是对我的莫大支持!

评论