Canal 依赖 canal-adapter 实现 MySQL 到 ES 的增量同步,需 MySQL 开启 ROW 格式 Binlog 并授权 canal 用户;ES 同步须用 es7.yml 配置,_type 必填 _doc,_id 需显式映射,字段类型须提前在 ES 中明确定义。

Canal 本身不直接写 ES,必须搭配 canal-adapter 才能完成 MySQL → ES 的增量同步;跳过 adapter 直接用 canal-server 是无效的。
MySQL 必须开启 ROW 格式 Binlog 并授权 canal 用户
Canal 依赖 MySQL 的 binlog 日志流,且只支持 ROW 格式 —— STATEMENT 或 MIXED 会导致解析失败或数据丢失。
- 修改
/etc/my.cnf(或你的 MySQL 配置路径),确保包含以下三项:
[mysqld] log-bin=mysql-bin binlog-format=ROW server_id=1
注意:server_id 不能为 0,也不能和 canal 的 slaveId 冲突(默认是 1234,可在 instance.properties 中改)。
- 创建并授权 canal 用户(RDS 用户可跳过授权,但需确认账号有
REPLICATION SLAVE权限):
CREATE USER 'canal'@'%' IDENTIFIED BY 'canal'; GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'canal'@'%'; FLUSH PRIVILEGES;
常见错误:ERROR 1236 (HY000): Could not find first log file name in binary log index file,通常是配置后没重启 MySQL,或 log-bin 路径不可写。
canal-adapter 同步 ES 需要正确配置 es7.yml(不是 es.yml)
Canal 1.1.5+ 版本起,ES 7.x+ 使用 es7.yml,旧版 es.yml 不兼容 —— 这是同步失败最常被忽略的点。
-
canal-adapter/conf/es7.yml中关键项必须匹配你的 ES 实例:
esMapping: _index: product_index _type: _doc # ES 7.x 已废弃 type,此处必须写 _doc,不能留空或填自定义值 _id: _id pk: id # 对应 MySQL 表主键字段名 sql: "SELECT a.id as _id, a.name, a.price, a.status FROM t_product a" commitBatch: 3000
注意:sql 中字段别名必须和 ES mapping 字段一致;_id 必须显式映射,否则 ES 会生成随机 ID,导致重复文档。
- ES 连接地址写法必须带协议和端口,例如:
http://es-cn-xxx.elasticsearch.aliyuncs.com:9200;若用 HTTPS,需额外配置sslEnabled: true并挂载证书。
启动顺序和日志排查要点
Canal 同步链路是:MySQL → canal-server → canal-adapter → ES。任一环节断开都会静默失败,必须逐层确认。
- 先启动
canal-server,检查logs/canal/canal.log是否出现Start CanalController successfully;再看logs/example/example.log是否有connect to mysql success和持续的parse event日志。 - 再启动
canal-adapter,重点看logs/adapter/adapter.log中是否有Es7SyncService sync start和commit to es成功记录;若只有load table mapping...却无后续,说明 SQL 没触发变更或表名大小写不匹配(Linux 下表名默认区分大小写)。 - ES 端用
GET /product_index/_count验证数据是否写入;若数量为 0,立刻查adapter.log最近 10 行,找java.net.ConnectException或MapperParsingException—— 前者是连不上 ES,后者多因字段类型冲突(如 MySQL 的datetime映射到 ES 的text字段)。
真实环境中最容易卡在 adapter 的 SQL 映射和 ES 字段类型对齐上,尤其是时间字段、JSON 字段、NULL 值处理;不要依赖自动 mapping,务必提前在 ES 中用 PUT /product_index 定义好明确的 date、keyword、float 类型。











