必须设为row,否则主从复制或数据恢复大概率出错;因statement仅记录sql原文,now()、uuid()等非确定性函数在主从库执行时间不同会导致结果不一致,如时间偏移、行数差异、值错位,甚至复制中断报错1032/1062。

为什么不能用 STATEMENT 模式
它只记 SQL 语句原文,像 NOW()、RAND()、UUID() 这类函数在主库和从库执行时间不同,结果就不一样。比如主库插入时用了 NOW() 记录当前时间,从库重放时再执行一次,时间就偏了——这不是 bug,是模式本身的设计缺陷。
常见错误现象包括:
- 从库数据比主库少几行或字段值对不上
-
SHOW SLAVE STATUS\G中出现Last_SQL_Errno: 1032或1062 - 用
mysqlbinlog解析日志时发现事件里没有具体行变更信息
如何安全地改成 ROW 模式
临时改(仅当前会话生效)不推荐,因为复制线程可能还在用旧格式写日志;必须全局+持久化。
操作步骤:
- 编辑
/etc/my.cnf(Linux)或my.ini(Windows),在[mysqld]段落下添加:binlog_format = ROW<br>binlog_row_image = FULL
-
binlog_row_image = FULL是关键补充:否则某些 UPDATE/DELETE 可能只记录新值,丢失旧值,导致闪回或修复失败 - 重启 MySQL:
systemctl restart mysql(或对应服务名) - 验证是否生效:
SHOW VARIABLES LIKE 'binlog_format';和SHOW VARIABLES LIKE 'binlog_row_image';都应返回ROW和FULL
MIXED 模式能不能当备选
可以,但别依赖它的“自动切换”。MySQL 判断哪些语句非确定性并不完全可靠,比如自定义函数、触发器里的逻辑,它可能仍按 STATEMENT 记录,然后出问题。
适用场景有限:
- 老系统迁移过渡期,没时间全量测试
ROW - 确认业务中完全不使用
sysdate()、uuid_short()等函数 - 有监控能实时捕获
Binlog_format_switch_event并告警
一旦用了 MIXED,就得定期查 SHOW BINARY LOGS; 输出里有没有 Format_desc 事件混着出现——那是危险信号。
容易被忽略的兼容性点
ROW 模式下,如果表没主键或唯一键,UPDATE/DELETE 会记录整行镜像,日志体积暴增,还可能拖慢复制。这不是配置问题,是表结构缺陷。
检查方法:SELECT table_schema, table_name FROM information_schema.tables WHERE table_schema NOT IN ('mysql','information_schema','performance_schema') AND (table_type='BASE TABLE') AND (table_schema, table_name) NOT IN (SELECT table_schema, table_name FROM information_schema.key_column_usage WHERE constraint_name='PRIMARY KEY' OR constraint_name='UNIQUE');
真正麻烦的是:有些中间件(如 Canal、Maxwell)默认只解析 ROW 日志,但要求 binlog_row_image = FULL,少配这一项,它们就收不到旧值,直接报错退出。











