MySQL 8.0 存储过程变慢主因是事务隔离级别默认为REPEATABLE-READ导致MVCC开销增大、DETERMINISTIC校验失效禁用执行计划复用、原子DDL重建耗时增加,以及utf8mb4_0900_ai_ci排序规则引发隐式转换和索引失效。

MySQL 8.0 存储过程执行变慢?先确认是不是用了 PREV 模式事务
MySQL 8.0 默认开启 transaction_isolation = 'REPEATABLE-READ',但部分存储过程在显式开启事务后,若未指定隔离级别,会继承会话默认值。而 5.7 中很多部署习惯性设为 READ-COMMITTED,导致相同逻辑在 8.0 下触发更重的 MVCC 版本链遍历,尤其在高并发更新场景下,SELECT ... FOR UPDATE 类语句延迟明显上升。
实操建议:
- 检查存储过程中是否含
BEGIN ... END+START TRANSACTION,并在开头显式加SET TRANSACTION ISOLATION LEVEL READ COMMITTED; - 用
SELECT @@transaction_isolation;验证当前会话实际生效值,别只看配置文件 - 若依赖可重复读语义,优先改用
SELECT ... LOCK IN SHARE MODE替代全表扫描式FOR UPDATE
CREATE PROCEDURE 中的 DETERMINISTIC 标志影响执行计划缓存
8.0 强化了对存储过程确定性的校验逻辑:即使你写了 DETERMINISTIC,只要内部调用了 NOW()、RAND()、用户变量(@var)或非确定性函数(如 UUID()),服务器会在首次调用时标记为 NOT DETERMINISTIC,并禁用该过程的执行计划缓存(query cache 已移除,但 prepared statement 缓存和 SP 内部语句的解析树复用仍受影响)。
常见错误现象:同一存储过程在 5.7 下多次调用耗时稳定,在 8.0 下每次耗时波动大,SHOW PROFILE 显示大量 checking permissions 和 init 阶段开销。
实操建议:
- 用
SHOW CREATE PROCEDURE proc_name;确认定义中是否真写了DETERMINISTIC,且内部无隐式非确定操作 - 避免在 SP 中使用
@var传参,改用IN/OUT参数;时间类逻辑尽量用输入参数代替NOW() - 若必须用随机值,提前生成好作为
IN参数传入,而非在 SP 内调用RAND()
8.0 的原子 DDL 导致存储过程重建变慢,但上线更安全
MySQL 8.0 将 DROP PROCEDURE/CREATE PROCEDURE 归入原子 DDL,意味着整个操作要写入数据字典事务日志、同步 binlog、刷盘后才返回成功。相比 5.7 的“先删后建”两步操作,单次部署耗时可能增加 3–10 倍(尤其在磁盘 I/O 压力大或 binlog_format=ROW 时)。
这不是性能倒退,而是保障一致性:5.7 中若 DROP 成功但 CREATE 失败,过程就永久丢失;8.0 要么全成功,要么回滚到原状。
实操建议:
- 批量更新多个存储过程时,不要逐个
DROP+CREATE,改用CREATE OR REPLACE PROCEDURE(8.0.19+ 支持),它复用原子 DDL 流程但减少元数据锁争用 - 上线前在从库执行
STOP SLAVE; SET GLOBAL binlog_format='STATEMENT';(仅临时),可显著降低主从延迟敏感场景下的部署耗时(注意:仅限可信、无函数/存储过程依赖的语句) - 监控
performance_schema.events_statements_history_long中CREATE PROCEDURE的LOCK_TIME和ROWS_AFFECTED,识别是否卡在元数据锁等待
字符集与排序规则变更让 CONCAT、LIKE 在 SP 内行为不一致
MySQL 8.0 默认字符集升为 utf8mb4,默认排序规则变为 utf8mb4_0900_ai_ci。这个新 collation 对大小写、重音、连字符的处理比 5.7 的 utf8mb4_general_ci 更严格。当存储过程中有字符串拼接后用于 WHERE col LIKE CONCAT('%', in_param, '%') 这类逻辑,可能因隐式转换导致索引失效,或匹配结果不同。
典型表现:5.7 下能走 col 索引,8.0 下变成全表扫描;或者 'café' LIKE 'cafe%' 在 5.7 返回 1,在 8.0 返回 0。
实操建议:
- 检查所有
CONCAT、REPLACE、UPPER相关表达式,确保左右操作数 collation 一致,必要时显式加COLLATE utf8mb4_0900_as_cs - 用
EXPLAIN FORMAT=TREE查看执行计划,重点看possible_keys和key是否为空 - 对模糊查询字段,考虑建立函数索引:
CREATE INDEX idx_col_like ON tbl ((LOWER(col)));(8.0.13+ 支持)
真正卡住性能的往往不是引擎本身,而是那些被 5.7 宽容掩盖的隐式类型转换、隔离级别误用和 collation 混用——这些在 8.0 里不会报错,但会让执行路径悄然变重。



















