mysql主库binlog_format设为statement易致从库同步失败,因非确定性函数或自增列引发数据不一致;5.7+启用gtid后混用statement与row会直接拒绝同步;动态修改需重启连接而非mysqld;log_bin关闭会导致“binary log is not open”错误;切row后需防控磁盘与网络压力。

MySQL主库binlog_format设为STATEMENT导致从库同步失败
STATEMENT格式在遇到非确定性函数(如NOW()、UUID()、SYS_DATE())或自增列插入时,从库重放SQL可能产生不一致,触发Slave_SQL_Running: No和Could not execute Write_rows event on table类错误。尤其在5.7+版本默认启用GTID后,STATEMENT与ROW混用会直接拒绝同步。
- 立即检查主库当前格式:
SHOW VARIABLES LIKE 'binlog_format'; - 确认是否含非确定性操作:
SELECT @@sql_log_bin, @@binlog_format;+ 查看慢日志中是否有UUID()或SYSDATE()写入 - 若主库已运行多年且应用未适配ROW,切勿直接改全局变量——需配合
SET SESSION binlog_format = 'ROW';逐会话验证
修改binlog_format必须重启mysqld?不,但有前提
5.7.7+支持动态修改binlog_format,但仅对新连接生效,已有连接仍沿用旧格式。所以光执行SET GLOBAL binlog_format = 'ROW';不够,必须确保所有写入连接重建。
- 先停应用或切流量,再执行:
SET GLOBAL binlog_format = 'ROW'; - 检查所有活跃连接是否已断开:
SHOW PROCESSLIST;,重点关注User为业务账号的Command为Query或Sleep的线程 - 强制刷新连接池(如Druid配置
removeAbandonedOnBorrow=true),或重启应用服务 - 验证新连接是否生效:
mysql -u app -p -e "SELECT @@binlog_format;"
从库报错“Binary log is not open”后无法启动IO线程
这是典型主库log_bin未开启或binlog_format被设为NONE的信号。从库尝试拉取binlog时发现主库根本没生成日志,直接拒绝连接。
- 登录主库确认:
SHOW VARIABLES LIKE 'log_bin';必须为ON;SHOW VARIABLES LIKE 'binlog_format';不能是NONE - 检查主库my.cnf是否误加了
skip-log-bin或disable_log_bin(常见于测试环境误复制配置) - 若主库确实关闭了binlog,必须重启mysqld——因为
log_bin是只读变量,SET GLOBAL无效 - 重启前备份
mysql-bin.index和最新binlog文件,避免重启后位点丢失
切换到ROW格式后磁盘暴涨、网络延迟升高
ROW格式记录每行变更的完整镜像,尤其批量UPDATE/DELETE时日志体积可达STATEMENT的数倍,容易撑爆磁盘或拖慢主从网络传输。
- 监控主库binlog增长:
du -sh /var/lib/mysql/mysql-bin.* | tail -20,对比切换前后单日增量 - 压缩binlog(5.7.4+):在my.cnf加
binlog_checksum=CRC32+binlog_row_image=MINIMAL(减少非变更字段记录) - 限制单次DML规模:应用层拆分大事务,避免
UPDATE t SET x=1 WHERE id BETWEEN 1 AND 1000000; - 从库启用
slave_parallel_workers > 0缓解SQL线程压力,但需确保slave_parallel_type = LOGICAL_CLOCK
最麻烦的是跨版本主从(如8.0主 + 5.7从),binlog_row_image参数不兼容,从库解析失败会静默跳过事件——务必在同版本环境验证后再上线。











