主从mysql json同步必须严格对齐版本、启用full binlog_row_image、临时禁用innodb_strict_mode(仅升级期),并校验binlog事件与json_valid结果。

主从 MySQL 版本必须对齐 JSON 序列化行为
ROW 格式本身能同步 JSON,但不同版本对 json_binary 的序列化细节不一致:5.7.12 前与 5.7.16+ 对 JSON_SET(col, '$.a', NULL) 的处理结果不同;8.0.22+ 又调整了 padding 和字节序。低版本从库读到高版本主库的 binlog 时,可能把完整 JSON 解析成 NULL 或空对象。
最稳妥的做法是主从都用同一小版本(如 8.0.33),至少保证主从同属一个大版本段(如都是 8.0.x,或都是 5.7.16+)。跨大版本同步(如 5.7 → 8.0)风险极高,不建议生产环境使用。
必须设 binlog_row_image = FULL
默认的 MINIMAL 模式在更新 JSON 字段时,可能只记录变更路径和新值,不保存整条 JSON 的二进制快照。从库重建行时缺少上下文,容易出错或丢键。
- 在主库执行:
SET GLOBAL binlog_row_image = 'FULL'; - 写入
my.cnf永久生效:binlog_row_image = FULL - 重启 MySQL 或重连从库使配置生效
从库禁用 innodb_strict_mode(仅限升级过渡期)
当从库版本较低(如 5.7)同步 8.0 主库的 JSON 写入时,innodb_strict_mode = ON 会导致 SQL Thread 因 JSON 校验失败而中断——例如主库存了一个合法但结构稍异的 json_binary,从库拒绝解析。
临时缓解方案(非长期推荐):
- 从库设置:
SET GLOBAL innodb_strict_mode = OFF; - 同时确认
sql_mode中不含STRICT_TRANS_TABLES或STRICT_ALL_TABLES - 该配置仅用于灰度迁移期,稳定后应恢复严格模式
验证同步是否真正可靠,别只看 SELECT 结果
表面查出来数据一样,不代表 binlog 事件没被截断或误解析。要直接 inspect binlog 内容:
- 在主库查 binlog 文件名:
SHOW MASTER STATUS; - 用
mysqlbinlog --base64-output=DECODE-ROWS -v mysql-bin.000001 | grep -A 10 -B 5 'your_json_column_name'查看实际 row event - 重点确认字段显示为
json_binary且长度合理(如 50+ 字节),而非NULL或极短二进制(如0x02) - 从库执行:
SELECT JSON_VALID(your_col), JSON_LENGTH(your_col) FROM t WHERE id = ?;,对比主库输出是否完全一致
JSON 同步的脆弱点不在语法,而在二进制序列化的隐式契约——只要主从对“怎么存 JSON”有一丝理解偏差,就可能静默丢数据。所以版本、binlog_row_image、校验开关这三项,一个都不能松。











