混合引擎破坏事务原子性:MyISAM不支持事务,GTID模式下其DML附着于InnoDB事务GTID,导致从库回放分裂、Executed_Gtid_Set失真、并行复制乱序及主键冲突等必然风险。

混合引擎(InnoDB + MyISAM)在多源复制中会破坏事务原子性
MySQL 5.7 多源复制本身不校验引擎一致性,但 GTID 模式下事务提交必须是原子的——而 MyISAM 不支持事务,INSERT INTO myisam_table 和 UPDATE innodb_table 同在一个 binlog event 里时,从库回放可能只成功执行前者,导致数据状态分裂。这不是“偶尔错”,而是设计层面的必然风险。
- GTID 要求每个事务有唯一、不可分割的标识;MyISAM DML 不生成独立 GTID,而是附着在前一个 InnoDB 事务的 GTID 下,造成
Executed_Gtid_Set记录失真 - 从库启用
slave_parallel_workers > 0时,MyISAM 表操作会被分发到不同 worker 线程,彻底打破语义顺序 -
RESET SLAVE ALL或通道重建后,MyISAM 表的 auto-increment 值不会被 GTID 追踪,容易与 InnoDB 表产生主键冲突
replicate-do-db 对混合引擎表的过滤行为不可靠
replicate-do-db 是全局参数,对所有通道生效,且仅在语句级(Statement)binlog 格式下按 USE db; 判断是否应用——但 MyISAM 表常被跨库访问(如 SELECT * FROM order_db.orders JOIN log_db.audit_log),这类语句会被误判为“不属于当前 db”,直接跳过,导致关联数据缺失。
- Row 格式下该参数失效:MySQL 5.7 默认
binlog-format=ROW,此时replicate-do-db完全不生效,所有库的变更都会进入 relay log - 即使强制用 Statement 格式,MyISAM 的非事务特性会让
CREATE TEMPORARY TABLE或LOCK TABLES类语句在从库无法重放,报错ERROR 1193 (HY000): Unknown system variable 'sql_log_bin' - 更隐蔽的问题:
replicate-ignore-table对 MyISAM 表无效——它只过滤 InnoDB 表的 row event,MyISAM 的 statement event 仍会执行
SHOW SLAVE STATUS 显示的 Seconds_Behind_Master 对混合引擎无意义
当从库同时同步多个主库且含 MyISAM 表时,Seconds_Behind_Master 值会剧烈抖动甚至显示 NULL,因为它依赖 SQL thread 的 last commit timestamp 与 IO thread 的最新 event 时间差——而 MyISAM 操作不写入 mysql.slave_relay_log_info 表,导致时间戳无法更新。
- 查状态必须用
SELECT * FROM performance_schema.replication_applier_status_by_worker WHERE CHANNEL_NAME = 'xxx'\G,否则看不到实际卡在哪条 MyISAM 语句上 - MyISAM 的
INSERT DELAYED语句在从库不支持,会转成普通 INSERT,但因无事务包裹,可能被并行 worker 插入乱序 - 一旦某个通道因 MyISAM 报错中断(如
ERROR 1032),其他通道的Seconds_Behind_Master也会归零或停滞,掩盖真实延迟
最易被忽略的点:备份导入时 MyISAM 表的 AUTO_INCREMENT 丢失
用 mysqldump --set-gtid-purged=ON 导出多源从库时,MyISAM 表的 AUTO_INCREMENT 值不会被写入 dump 文件(因为不参与事务),恢复后从库的自增起点与主库脱节。后续插入若触发主键冲突,slave-skip-errors 会跳过但不修复,错位持续存在。
- 验证方法:
SELECT TABLE_SCHEMA, TABLE_NAME, AUTO_INCREMENT FROM information_schema.TABLES WHERE ENGINE='MyISAM' AND TABLE_SCHEMA NOT IN ('mysql','information_schema');在主从间比对 - 修复手段不是改
auto_increment值,而是停掉对应通道,用ALTER TABLE ... AUTO_INCREMENT = N手动对齐,再START REPLICA FOR CHANNEL - 根本解法:把所有 MyISAM 表迁移到 InnoDB,执行前确认
innodb_file_per_table=ON且磁盘空间充足


















