唯一可靠方式是修改配置文件并重启mysqld;SET GLOBAL仅临时生效且极不稳定,必须查SELECT @@global.binlog_format确认,返回ROW才真正生效。

直接改配置文件并重启 mysqld,是唯一可靠的方式;运行时 SET GLOBAL binlog_format = 'ROW' 仅在部分旧版本临时生效,且极不稳定,不建议用于生产。
确认当前 binlog_format 值是否真的生效
执行 SELECT @@binlog_format; 看返回值,但注意:这个值可能只是会话级缓存,不代表实际写入 binlog 的格式。真正起作用的是全局变量 @@global.binlog_format,所以务必查 SELECT @@global.binlog_format;。如果返回 STATEMENT 或 MIXED,说明配置没生效或被覆盖。
常见干扰项包括:
- 配置文件中多个
binlog-format出现(比如my.cnf和my.ini同时存在,或被 include 进来的其他文件覆盖) - 启动时用了命令行参数
--binlog-format=STATEMENT,会强制覆盖配置文件设置 - 某些云数据库(如阿里云 RDS、腾讯云 CDB)禁止用户修改该参数,需通过控制台或工单申请
正确修改 my.cnf 配置并重启服务
在 [mysqld] 段落下添加或修改这一行:
binlog-format = ROW
注意:binlog-format 是配置项名,不是变量名;大小写不敏感,但推荐全大写保持一致性。不要写成 binlog_format(下划线形式只在 SQL 变量中用,如 SET GLOBAL binlog_format)。
重启前检查:
- 确保 MySQL 有权限读取该配置文件(特别是使用非标准路径时,可用
mysqld --help --verbose | grep "Default options"查找加载顺序) - 确认没有语法错误(比如漏掉等号、多出空格、用了中文标点)
- 重启后立刻执行
SELECT @@global.binlog_format;验证,而不是只看SHOW VARIABLES LIKE 'binlog_format';——后者可能显示会话值
ROW 模式下必须注意的两个硬性前提
启用 ROW 后,MySQL 不再记录原始 SQL,而是记录每行变更的前后镜像(Before Image / After Image)。这带来两个关键约束:
-
UPDATE和DELETE必须能精确定位到行 —— 所以目标表**必须有主键或唯一非空索引**,否则会报错Table definition is ambiguous: no primary key or unique not null key found - 临时表(
CREATE TEMPORARY TABLE)在ROW或MIXED模式下**不会被复制**,这是设计行为,不是 bug。如果业务依赖从库临时表数据,必须重构逻辑
另外,ALTER TABLE 类 DDL 在 ROW 模式下会触发整表重写,生成海量 binlog(例如千万级表执行 ADD COLUMN),务必避开业务高峰。
别信“动态切换”这种说法
网上很多教程说 SET GLOBAL binlog_format = 'ROW' 就能热切,这是严重误导。实际情况是:
- MySQL 5.7+ 已明确禁止运行时从
ROW切回STATEMENT,因为临时表语句不会写入 binlog,切回去会导致从库缺失结构 - 即使成功执行了
SET GLOBAL,新连接可能仍继承旧格式(尤其使用连接池时),而旧连接继续用原格式,造成 binlog 混合,复制中断 - 某些版本(如 Percona Server 5.6)会在 error log 中打印警告:
Setting binlog_format to ROW on a running server is not recommended
真正安全的做法只有一种:停写、改配置、重启、验证、恢复写入。任何绕过重启的方案,在主从架构里都埋着数据不一致的雷。


















