canal php消费需mysql配置row模式、正确权限及server_id,php端须用swoole长连接而非curl轮询,位点管理、幂等性、es mapping需自行实现。

Canal 能用 PHP 消费,但不是“装个包就能跑”,MySQL 侧配置错一个参数,PHP 端连 connect() 都会失败——90% 的问题出在 MySQL,不在 PHP 代码里。
MySQL 必须开 ROW 模式 + 正确权限,否则 Canal 启动就报错
Canal 不是查表,它靠伪装成从库拉 binlog 流。如果 binlog_format 是 STATEMENT 或 MIXED,UPDATE/DELETE 只记 SQL 语句,Canal 解不出哪一行变了,直接丢数据。
-
log_bin必须为ON(执行SHOW VARIABLES LIKE 'log_bin';确认) -
binlog_format必须设为ROW,且写进my.cnf的[mysqld]段,不能只在 session 里 SET - 专用账号至少要带这三权:
SELECT、REPLICATION SLAVE、REPLICATION CLIENT -
server_id不能是1(Canal 默认拒绝连接),建议设为1001这类非 1 值
常见报错:ERROR 1236 (HY000): Could not find first log file name in binary log index file → 缺 REPLICATION SLAVE;Access denied; you need (at least one of) the SUPER privilege(s) → 权限没刷:别忘了 FLUSH PRIVILEGES;
PHP 不能用 cURL 轮询 Canal HTTP 接口
Canal 的 HTTP 模式不支持长轮询,每次 file_get_contents("http://canal:8080/") 都是新连接,延迟高、易被限流,还可能漏 event。
- 必须用长连接方案:推荐
swoole+xingwenge/canal_php(注意不是已废弃的同名包) -
canal-php封装了 socket 连接、protobuf 解码、ack/rollback流程,直接取$rowChange->getBeforeColumnsList()就行 - 别自己用
fsockopen硬解 protobuf——格式复杂,字段嵌套深,极易出错 - 连接失败时,
CanalClient::connect()抛出的异常里含真实原因:Authentication failed是账号密码错,Unknown database是 Canal 配置的destination名不对
同步到 ES 或 Redis 时,位点管理和幂等性得自己兜底
Canal 只负责推原始 binlog event,不关心你 PHP 里写 Redis 失败还是 ES mapping 冲突。它默认 ack 后就前进位点,失败=永久丢失。
- 每次消费完一个 batch,必须手动
$client->ack($batchId);失败则立刻$client->rollback($batchId),否则下次拉取跳过这批 -
batchSize别设太大(比如 1000):Canal server 的 netty 缓冲区可能撑不住,导致连接断开;建议从50起调 - ES 写入前必须提前建好
mapping:Canal 不传类型信息,ES 自动猜类型(如首次"0"当keyword,后续传整数0就报MapperParsingException) - 对空值字段(如
updated_at = NULL),PHP 里得主动转成NULL或字符串"null",避免 ES 收到空字符串引发类型冲突
真正卡住人的从来不是怎么连上 Canal,而是位点没存稳、幂等没做全、ES mapping 没预设——这些都得 PHP 自己扛,Canal 一概不管。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











