mysql 8.0 中 -r 已被弃用,必须显式使用 --routines 才能导出函数和过程;即使启用该选项,还需处理 definer 权限、字符集变更及跨版本兼容性问题。

加了 -R 却没导出函数和过程?不是参数没生效,是它根本没被识别——因为 -R 在 MySQL 8.0 默认已被弃用,必须显式用 --routines。
mysqldump -R 在 MySQL 8.0 中已失效
MySQL 8.0 客户端(尤其是 8.0.26+)默认禁用了短选项 -R 的别名功能,它不再自动映射为 --routines。执行 mysqldump -u root -p -R mydb 看似成功,但生成的 SQL 文件里完全不会出现 CREATE PROCEDURE 或 CREATE FUNCTION 语句。
- 验证方法:导出后 grep
CREATE PROCEDUREroutines.sql —— 若无输出,说明没导出 - 根本原因:8.0 削减了对旧短选项的支持,
-R不再是--routines的等价写法 - 正确写法只能是
--routines,且必须与数据库名一起使用,不能单独存在
只加 --routines 还不够:DEFINER 和权限会拦路
即使用了 --routines,导入时大概率遇到 ERROR 1449 (HY000): The user specified as a definer ('xxx'@'%') does not exist。这是因为导出的 CREATE PROCEDURE 语句里硬编码了 DEFINER=`user`@`host`,而目标库没有该用户或权限不匹配。
- 开发/测试环境:导入前在目标库执行
SET GLOBAL log_bin_trust_function_creators = 1,并加--skip-definer(8.0.26+ 支持) - 生产环境:不要删 DEFINER;先在目标库创建同名用户并赋权:
CREATE USER 'xxx'@'%' IDENTIFIED BY 'pwd'; GRANT EXECUTE ON mydb.* TO 'xxx'@'%'; - 临时绕过:用
sed -i 's/DEFINER=`[^`]*`@`[^`]*`//g' routines.sql清除,等效于改用SQL SECURITY INVOKER,但需确认调用者权限是否足够
跨版本迁移时,5.7 导出的 routines 在 8.0 导入失败
用 5.7 的 mysqldump 工具导出的存储过程,在 8.0 上 source 执行会报语法错误或权限拒绝,不是内容问题,而是元数据结构和校验逻辑变了。
- 必须用目标版本的客户端导出:即升级到 8.0 后,用 8.0 的
mysqldump连接 5.7 实例(支持跨版本读取) - 避免依赖
mysql.proc:5.7 的过程元数据存在mysql.proc表,8.0 已废弃,改用information_schema.routines(只读),直接 dump 5.7 的mysql.proc行在 8.0 插入会失败 - 字符集陷阱:5.7 过程里写的
IF @a = '测试'在 8.0 可能恒为 false,因默认 collation 从utf8mb4_general_ci变成utf8mb4_0900_as_cs(大小写敏感)
真正容易被忽略的是:--routines 导出的内容无法按类型分离(PROCEDURE 和 FUNCTION 混在一起),也没有开关控制是否包含触发器——--triggers=false 必须显式加,否则导入时可能触发 ERROR 1235(多触发器冲突)。这不像表导出可以选表,例程导出是“全有或全无”的底层行为。











