mysqldiff 默认不校验 ENGINE 等表级属性,需显式加 --skip-table-options=0 才比对引擎、字符集等;否则即使 InnoDB 与 MyISAM 混用也会显示“无差异”,而 ENGINE 差异会导致事务、锁、外键等运行时行为严重不一致。

mysqldiff 默认不校验 ENGINE,必须显式加参数
默认执行 mysqldiff 时,它只比对列定义、索引、主键等基础结构,ENGINE、ROW_FORMAT、AUTO_INCREMENT 这类表级属性会被跳过。这会导致明明两个库的表一个用 InnoDB、一个还是 MyISAM,输出却显示 “No differences found”。
实操建议:
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
- 加
--skip-table-options=0(注意是=0,不是--skip-table-options不带值)才能启用引擎、字符集、排序规则等比对 - 若只想聚焦引擎差异,可配合
--exclude-tables=".*"排除所有表内容比对,只留元数据层检查 - MySQL 8.0.19+ 中
INFORMATION_SCHEMA.TABLES的ENGINE字段已可靠反映运行时真实引擎,但mysqldiff仍需参数触发读取
直接查 information_schema.tables 是最稳的引擎一致性快检方式
当无法装 mysqldiff,或需要绕过工具链快速确认所有表是否已统一为 InnoDB,直接查元数据表最直接。
常见错误现象:升级后执行 SHOW VARIABLES LIKE 'default_storage_engine' 返回 InnoDB,但老表仍是 MyISAM —— 因为该变量只影响新建表,不改造存量表。
实操建议:
- 执行:
SELECT table_schema, table_name, engine FROM information_schema.tables WHERE table_schema NOT IN ('mysql','information_schema','performance_schema','sys') AND engine != 'InnoDB'; - 结果为空才说明非系统库全为
InnoDB;若有返回,需逐个验证是否仍在被业务读写(如日志表、统计缓存表可能有意保留MyISAM) - 避免用
SHOW CREATE TABLE结果判断——它可能还写着ENGINE=MyISAM,但实际运行时已被 MySQL 8.0+ 隐式转为InnoDB,此时元数据中的engine值才是真相
ENGINE 差异会引发哪些 runtime 行为不一致
表面只是 DDL 里一个单词不同,但 ENGINE=InnoDB 和 ENGINE=MyISAM 在事务、锁、崩溃恢复、外键支持上完全不同,线上混用极易出问题。
容易被忽略但后果严重的点:
-
INSERT ... ON DUPLICATE KEY UPDATE在MyISAM下不生效,会报错;InnoDB下正常——ORM 自动生成的 upsert 逻辑可能突然崩 -
SELECT ... FOR UPDATE在MyISAM下静默忽略,不加锁;InnoDB下真加行锁——并发更新场景下数据会静默错乱 - 外键约束在
MyISAM下完全不校验,INSERT时不会报Cannot add or update a child row错误,导致脏关联数据堆积 -
mysqldump --single-transaction对MyISAM表无效,备份期间可能读到不一致状态
修复 ENGINE 不一致不能只靠 ALTER TABLE
把 MyISAM 表改成 InnoDB 看似一条 ALTER TABLE t ENGINE=InnoDB 就完事,但线上大表可能卡住整个库。
性能 / 兼容性影响:
- MySQL 5.7 下,
ALTER TABLE ... ENGINE=InnoDB是“重建表”操作,全程锁表;8.0+ 支持ALGORITHM=INSTANT的仅限加列/删列,改引擎仍需重建 - 含全文索引的
MyISAM表不能直接转InnoDB(二者全文索引结构不兼容),必须先DROP FULLTEXT INDEX,再ALTER,最后重建索引 - 如果表有
AUTO_INCREMENT值极大(比如 10 亿+),InnoDB的聚簇索引可能导致插入变慢,需提前评估 - 别忘了检查
innodb_file_per_table是否开启——关闭状态下所有InnoDB表共用一个 ibdata1,后续扩容和清理会非常被动
SHOW CREATE TABLE 里写了什么,就信了什么。引擎类型必须以 information_schema.tables.engine 为准,且得人工确认每张表的业务语义是否允许变更。

















