Canal GTID 位点失效解决方案
文档背景:生产 Canal 实例因主库 binlog 被清理(purge),导致持久化位点失效、无法继续订阅,持续报错 errno 1236。本文完整记录该问题的现象、根因、排查思路与解决方案。本次生产故障已通过「删实例 + 重建」方案成功恢复。
脱敏说明:本文为脱敏版本,涉及环境地址、域名、IP、账号密码、实例名、binlog 文件名、位点、GTID 串等敏感信息均已替换为占位符(<…>),结构与操作命令完整保留,可直接套用到其他环境。
1. 问题现象
Canal 实例启动后反复重试,destination 一直处于异常状态,无法正常消费 binlog。实例日志(logs/<实例名>/<实例名>.log)持续输出以下两类错误:
错误一:GTID 模式(开启 GTID 时)
ERROR c.a.o.canal.parse.inbound.mysql.dbsync.DirectLogFetcher – I/O error while reading from client socket
java.io.IOException: Received error packet: errno = 1236, sqlstate = HY000
errmsg = The slave is connecting using CHANGE MASTER TO MASTER_AUTO_POSITION = 1,
but the master has purged binary logs containing GTIDs that the slave requires.
关键日志(启动时找到的旧位点):
prepare to find start position just last position
{"postion":{"gtid":"<GTID串>",
"journalName":"<binlog文件名>","position":<position>,"timestamp":<时间戳>}}
错误二:关闭 GTID 后(file+position 模式)
java.io.IOException: Received error packet: errno = 1236, sqlstate = HY000
errmsg = Could not find first log file name in binary log index file
即 Canal 拿着旧的 binlog 文件名(<binlog文件名>)+ position 去 dump,但主库的 binlog 索引文件里已经没有这个文件了。
2. 根因分析
| 直接原因 | Canal 持久化的消费位点(cursor)指向的 binlog 已被主库清理(purge),无法继续 dump |
| 深层原因 | 消费端长期停止 / Canal 故障停机 / 消费延迟过大,期间主库按保留策略清理了 binlog;Canal 恢复后拿着旧位点去拉,主库校验失败 |
| GTID 模式下的表现 | MySQL 开启 MASTER_AUTO_POSITION=1 后,会校验从机(即 Canal)提交的 GTID 集合,如果集合中包含已被 purge 的事务,直接拒绝并返回 1236 |
| 非 GTID 模式下的表现 | 直接用 journalName+position 定位,binlog 文件不存在时返回 1236「Could not find first log file name」 |
核心结论:该问题不是连接问题、也不是配置语法问题,而是位点过期。binlog 已被清理的历史增量无法找回,只能让 Canal 丢弃旧位点、从主库当前最新位点重新订阅。
3. 排查思路(如何定位是不是位点失效)
3.1 确认 MySQL 连接正常
报错出现前先排除连接问题:
# 在 Canal Server 机器上测试到主库的连通性
telnet <源MySQL主机> 3306
或确认实例配置中 canal.instance.master.address 正确。若连接正常、报错集中在 dump 阶段(errno 1236),即为位点问题。
3.2 判断 GTID 与 binlog 是否被清理
在主库执行:
— 当前 binlog 文件列表
SHOW BINARY LOGS;
— 或 MySQL 8.0+
SHOW MASTER STATUS;
— binlog 保留策略
SHOW VARIABLES LIKE 'binlog_expire_logs_seconds';
SHOW VARIABLES LIKE 'expire_logs_days';
若错误日志中的 journalName(如 <binlog文件名>)已不在 SHOW BINARY LOGS 列表中,确认 binlog 已被清理,即位点失效。
3.3 定位 Canal 的位点存哪(重要,决定清法)
Canal 的位点(cursor)持久化位置取决于部署模式:
| 普通模式(conf/ 本地实例) | 本地文件 conf/<实例名>/meta.dat |
| admin manager 模式(有 conf/spring/、canal_local.properties) | 独立持久化在 admin 侧(Web 操作或 admin 数据库) |
admin manager 模式的判定:
cat /opt/canal/server/conf/canal_local.properties
# 出现 canal.admin.manager = <admin地址>:8089 即为 admin 模式
本地 meta.dat 排查(admin 模式下本地 conf/ 只有 example 实例,其它实例无本地 meta.dat):
find /opt/canal/server -name "meta.dat"
3.4 查看实例当前配置内容
- admin 模式:登录 admin Web(http://<canal-admin域名>:8089,默认账号 admin/<默认密码>)→「实例管理」→「修改」查看配置内容。
- 重点检查:
- canal.instance.master.journal.name / master.position / master.gtid / master.timestamp 是否带旧值
- canal.instance.gtidon 是否为 false
4. 解决方案
方案一:admin Web 修改配置清空位点(优先尝试)
适用于 admin manager 模式。1.1.5 的 Web 操作菜单只有「修改 / 删除 / 启动 / 停止 / 日志」,没有「重置位点」按钮,只能手动清配置。
canal.instance.gtidon = false
canal.instance.master.gtid =
canal.instance.master.timestamp =
canal.instance.master.journal.name =
canal.instance.master.position =
注意事项:若配置已按上述清空,但实例日志仍显示旧位点(prepare to find start position just last position + 旧 journalName/gtid),说明 cursor 独立持久化、不随配置修改清除,此方案无法解决,请直接采用方案二或方案三。
方案二:删除实例 + 重建(本次实际采用,已验证成功)
位点 cursor 绑定实例,删除实例可连带清除;前提是已备份配置内容。本次生产故障即通过该方案成功恢复。
方案三:直接清 admin 数据库中的持久化 cursor(Web 无法解决时)
适用场景:配置已清空,但日志仍显示旧位点(说明 cursor 独立持久化,Web 改不到)。
mysql -h <admin数据库主机> -P 3306 -u <账号> -p <库名>
SHOW TABLES;
SELECT * FROM <表名> WHERE <字段> LIKE '%<旧gtid前20位>%'\\G
SELECT * FROM <表名> WHERE <字段> LIKE '%<旧binlog文件名>%'\\G
UPDATE <表名> SET <字段> = REPLACE(<字段>, '<旧binlog文件名>', ''), modified_time = NOW() WHERE name = '<实例名>';
— 旧 position / gtid 值同理
5. 关键原理:为什么必须「同时」清 timestamp 和 cursor
Canal 启动时找起始位点的优先级:持久化 cursor(last position)优先于配置中的位点项。
| 都不清 | 旧 cursor(旧 binlog 文件 + position + 旧 GTID) | 报错(初始状态) |
| 只清 cursor | 配置中的 master.timestamp(可能更早的过期时间点) | 仍报错(该时间点的 binlog 也可能已 purge) |
| 只清 timestamp | 旧 cursor | 仍报错 |
| 两者都清 | 主库当前最新 binlog | 正常恢复 |
因此即使配置里 journal.name/position/gtid 已清空,若 master.timestamp 还带着旧时间戳、或存在独立持久化的 cursor,问题不会消失。
代价说明:清位点会跳过被 purge 的那段历史增量(本来也已无法找回),从当前时刻起正常订阅新数据。
6. 预防与根治建议
| 增大 binlog 保留时间 | 主库设置 binlog_expire_logs_seconds = 604800(7 天)或更长,确保 Canal 停机/延迟期间 binlog 不被清理 |
| 监控 Canal 消费延迟 | 消费位点滞后超过阈值(如 binlog 保留期的 50%)触发告警 |
| 消费端及时 ACK | 确认下游消费正常,避免位点堆积 |
| 不要随意删 meta.dat / 清位点 | 正常情况清位点 = 丢增量,仅在本问题(已无法找回)时使用 |
| 升级 Canal 版本 | 新版 admin 提供更完善的位置管理能力,可评估升级 |
7. 附录
7.1 本文实例环境(脱敏)
| Canal 版本 | 1.1.5(deployer + admin) |
| 部署模式 | admin manager 管理(canal.admin.manager = <admin地址>:8089) |
| admin Web | http://<canal-admin域名>:8089(默认账号 admin/<默认密码>) |
| admin 数据库 | <admin数据库主机>:3306,库名 <库名> |
| 故障实例 | <实例名>(源库 <源MySQL主机>:3306) |
| 故障位点 | journalName=<binlog文件名>, position=<position> |
7.2 关键日志定位词速查
# 实例日志
tail -f logs/<实例名>/<实例名>.log
# 重点关键字
grep -E "errno = 1236|purged binary logs|Could not find first log file|find start position" logs/<实例名>/<实例名>.log
7.3 相关链接
- Canal 官方文档:https://github.com/alibaba/canal
- 本文配套文档:[Canal 升级 jar 包操作文档-FastJSON示例.md]
网硕互联帮助中心




评论前必须登录!
注册