canal 实时同步延迟通常低于100ms,但php需通过canal-php等客户端消费binlog事件;mysql必须启用row模式binlog并授予replication slave/client权限,否则丢数据或启动失败。

Canal 实时同步的延迟通常能压到 100ms 内,但 PHP 端无法直接消费 Canal 的原始数据流——你必须用 canal-php 这类客户端库,或自己对接 Canal 的 TCP/HTTP 协议,否则根本收不到变更事件。
MySQL 必须开 ROW 模式 binlog,且权限要给足
Canal 不是靠查表、也不是靠触发器,它靠的是 MySQL 主库推送的 binlog。如果 binlog_format 是 MIXED 或 STATEMENT,UPDATE 和 DELETE 可能只记录 SQL 语句,没法还原出具体哪一行变了,Canal 就会丢变更、漏数据。
-
log_bin必须为ON,检查命令:SHOW VARIABLES LIKE 'log_bin'; -
binlog_format必须设为ROW,不能只写在 session 级,得写进my.cnf的[mysqld]段并重启 MySQL - 授权语句里缺
REPLICATION SLAVE会导致 Canal 启动时报ERROR 1236 (HY000): Could not find first log file name in binary log index file;缺REPLICATION CLIENT则连SHOW MASTER STATUS都执行不了
PHP 不能直连 Canal server,得靠 canal-php 或自建消费者
Canal server 默认暴露的是 TCP 端口(如 11111)或 HTTP 接口(需开启 canal.serverMode=http),PHP 原生不带长连接保活、无自动重连、不解析 protobuf 格式的 binlog event——硬连等于白搭。
- 推荐用
xingwenge/canal_php:它封装了 socket 连接、protobuf 解码、ack/rollback流程,支持getWithoutAck+ack的可靠消费模式 - 别用
file_get_contents("http://canal:8080/...")轮询:HTTP 模式下 Canal 不支持长轮询,每次请求都新建连接,延迟高还容易被限流 - 注意
canal-php的batchSize参数:设太大(比如 1000)可能超 Canal server 的netty.so.rcvbuf缓冲区,导致连接断开;建议从 50 起调
同步逻辑写在 PHP 里,但“失败重试”不能只靠 try-catch
Canal 推送的是原始 binlog event,它不保证下游处理成功。比如你用 PHP 更新 Redis 缓存失败了,Canal 并不知道,下次拉取还会跳过这批 event——数据就永久不一致了。
- 必须手动
rollback当前 batch:调用$client->rollback($batchId),让 Canal 重发这批 event - 别在单次消费循环里做耗时操作(如调远程 API、写大文件):超时会导致
ack失败,Canal 触发重推,造成重复处理 - 幂等性得自己做:比如用
UPDATE的主键 + 操作类型(INSERT/UPDATE)拼成唯一 key,写入 Redis 的SETNX或数据库去重表
最常被忽略的一点:Canal 的 instance.properties 里 canal.instance.filter.regex 是 Java 正则,不是 PCRE;写 db.table 要双反斜杠 db\.table,否则匹配失效,PHP 端一条消息都收不到。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











