ROW格式同步JSON字段丢数据,因主从MySQL版本对JSON二进制序列化实现不一致:5.7.8+引入JSON类型但早期版本(如5.7.12前)与5.7.16+的NULL判定逻辑不同,8.0.22+优化存储导致字节序或padding变化,低版本从库解析失败。

ROW 格式能正确同步 JSON 字段,但必须确保主从 MySQL 版本对 JSON 类型的序列化行为一致,否则会出现 NULL、空对象或解析失败。
为什么 ROW 格式同步 JSON 有时会丢数据?
MySQL 的 binlog_format = ROW 在记录 JSON 字段变更时,并不直接存储原始 JSON 文本,而是将其序列化为内部二进制格式(JSONB 类似结构)。不同版本对 JSON 序列化的实现有细微差异:
- MySQL 5.7.8+ 引入 JSON 类型,但早期版本(如 5.7.12 之前)对
JSON_EXTRACT()返回 NULL 的判定逻辑与 5.7.16+ 不同 - MySQL 8.0.22+ 优化了 JSON 内部存储,部分字段在 binlog 中的字节序或 padding 行为变化,导致低版本从库解析失败
- 若主库写入
JSON_SET(json_col, '$.a', NULL),旧版从库可能将该路径置为空字符串而非删除键,造成语义不一致
如何验证当前 JSON 同步是否可靠?
不要只看 SELECT 结果,要检查 binlog 事件本身是否完整承载了 JSON 变更:
将一个或多个视频上传至YouTube。当用户想“上传到YouTube”“发YouTube”“批量上传”“upload to YouTube”“post videos to YouTube”或发布到YouTube时使用此技能。
- 在主库执行:
SHOW VARIABLES LIKE 'binlog_format';确认是ROW - 用
mysqlbinlog --base64-output=DECODE-ROWS -v mysql-bin.000001 | grep -A 10 -B 5 '"json_col"查看实际写入的 row event 内容 - 重点观察
@N列对应 JSON 字段的值是否为NULL、json_document或json_binary—— 若显示为json_binary且长度异常短(如只有 2 字节),说明序列化被截断 - 在从库执行
SELECT JSON_VALID(json_col), JSON_LENGTH(json_col) FROM tbl WHERE ...,对比主库结果是否一致
升级或跨版本部署时 JSON 同步的关键配置
主从版本差越大,JSON 兼容风险越高。以下配置可显著降低出错概率:
- 强制统一
binlog_row_image = FULL:避免因 MINIMAL 模式省略 JSON 字段全量快照,导致从库无法重建值 - 禁用
innodb_strict_mode = OFF(尤其在 5.7→8.0 升级中):防止从库因 JSON 校验失败而停止 SQL Thread - 避免在 DDL 中混用
JSON和TEXT:例如主库用ALTER TABLE t MODIFY jcol JSON,但从库仍为TEXT,ROW 事件会因类型不匹配被跳过 - 若使用 GTID,确认
enforce_gtid_consistency = ON且所有 JSON 操作都在事务内 —— 非事务性 JSON 函数(如JSON_PRETTY())不会写入 binlog
遇到 JSON 字段同步为 NULL 怎么快速定位?
这不是网络或权限问题,90% 是主从 JSON 实现层不兼容。按顺序排查:
- 查错误日志:
grep -i "json\|binary\|row" /var/log/mysql/error.log,重点关注Could not parse json value或Invalid JSON binary format - 比对主从
SELECT VERSION(), @@json_validity_check—— 某些定制版 MySQL 会关闭 JSON 校验开关 - 临时切换为
MIXED格式重放一次变更,看是否能绕过序列化问题(仅用于诊断,不可长期使用) - 最稳妥方案:在应用层把 JSON 字段转为
TEXT存储,配合JSON_VALID()校验,牺牲一点语义能力换稳定性
JSON 同步真正的坑不在语法,而在二进制序列化层——同一份 JSON 文本,在 5.7.25 和 8.0.33 的 binlog 里可能是两个完全不同的字节流。别依赖“都是 ROW 格式就一定行”,版本组合必须实测。

















