mysql 8.0相比5.7在sql执行流程中元数据加载路径、优化器成本模型、ddl原子性和触发器执行时机四大底层机制发生重构:5.7依赖.frm文件反复解析,8.0统一走事务性数据字典缓存复用;5.7用启发式规则选执行计划,8.0默认启用cost model结合直方图精准估算;5.7 ddl非原子易致不一致,8.0支持instant加列与自动回滚;触发器均不参与explain,但8.0初始化开销更低,性能受performance_schema采集影响更大。

SQL执行流程里元数据加载路径变了
5.7 读表结构要打开 .frm 文件,每次触发器、存储过程、视图引用都得重新解析;8.0 全部走事务性数据字典(mysql.innodb_table_stats 等 InnoDB 表),元数据只加载一次、缓存复用。这对上千张表的实例特别明显——SHOW TABLES、INFORMATION_SCHEMA 查询快几倍,高并发下建表/改表也不再卡在元数据锁上。
优化器选执行计划的依据更重成本模型
5.7 的优化器主要靠启发式规则,比如“小表驱动大表”,但对复杂 JOIN 或子查询容易误判;8.0 引入 Cost Model,默认启用 STRICT_ALL_TABLES 和更细粒度的统计信息(包括直方图),能真实估算 WHERE 条件过滤后的行数、索引扫描代价。这意味着:
• 同一条 SELECT * FROM a JOIN b ON a.id = b.a_id WHERE b.status = 'done',8.0 更可能选对索引;
• 如果没收集直方图(ANALYZE TABLE 没跑),8.0 反而可能比 5.7 更保守、选错计划;
• EXPLAIN FORMAT=TREE 在 8.0 才有,能看到 Hash Join 节点,5.7 只有 Nested Loop。
DDL不再是“黑盒操作”,执行阶段可感知原子性
5.7 的 ALTER TABLE 是非原子的:加列失败时可能留下半截表、.frm 和 ibd 不一致,只能靠备份回滚;8.0 的 DDL 在 Server 层和引擎层协同完成,失败自动回退,且支持 ALGORITHM=INSTANT 这种跳过数据重写的路径。但要注意:
• INSTANT 加列只对末尾新增、默认值为 NULL/字面量、无 FULLTEXT 索引的 InnoDB 表生效,否则降级为 INPLACE 或 COPY;
• SHOW CREATE TABLE 输出里没出现 ALGORITHM=INSTANT,说明没走秒级路径;
• 已有数据行的新增列是 lazy fill —— 第一次访问才补默认值,不是建表时就写满。
触发器和存储过程不再参与优化器决策
很多人误以为 EXPLAIN 能看到触发器耗时,其实不能。触发器在 5.7 和 8.0 都属于“语句执行后同步调用”,不进优化器 Cost Model,也不出现在 EXPLAIN FORMAT=TREE 里。区别在于:
• 5.7 触发器执行前反复打开表、读 .frm,初始化开销大;
• 8.0 元数据已缓存,但若 performance_schema.events_statements_history_long 开着,默认采集会拖慢批量触发器;
• INSERT ON DUPLICATE KEY UPDATE 场景下,8.0 的间隙锁范围更精准、隐式锁检测更快,所以“卡住”概率低——但这依赖 innodb_deadlock_detect=ON(8.0 默认开启);
• 查触发器实际耗时,只能查 performance_schema.events_statements_history_long,不是看 EXPLAIN。
真正影响执行流程的,从来不是语法糖或新函数,而是元数据怎么读、代价怎么算、DDL 怎么落盘、触发器在哪一刻介入——这些底层链条一旦松动或重构,应用表现就会突变。升级前最该盯的,不是“能不能用新语法”,而是“老 SQL 在新流程里会不会被重排计划、被锁住、被采集拖慢”。











