mysqldump导出存储过程必须加--routines参数,否则不导出过程函数;需注意definer权限、sql_mode兼容性、字符集统一及mysql版本特性差异。

mysqldump 导出存储过程时必须加 --routines 参数
默认情况下 mysqldump 不导出存储过程、函数、事件,只导表结构和数据。漏掉这个参数,导入后 SHOW PROCEDURE STATUS 会为空,但又不报错,容易误以为迁移成功。
实操建议:
- 导出完整数据库(含过程):
mysqldump -u root -p --routines --no-create-info --no-data --skip-triggers mydb > mydb_routines.sql - 如果只要过程不导表,用
--no-create-info --no-data;若要连建表语句一起导,去掉这两个参数,但注意目标库不能已存在同名对象 -
--routines会同时导出PROCEDURE和FUNCTION;如只需过程,后续可手动删掉CREATE FUNCTION块 - MySQL 8.0+ 默认开启
log_bin_trust_function_creators=OFF,导入含DEFINER的过程可能报错ERROR 1418,需提前在目标库执行SET GLOBAL log_bin_trust_function_creators = 1
导入前检查 DEFINER 是否存在且有权限
存储过程定义里常带 DEFINER=`user`@`host`,如果目标服务器没有该用户,或用户无 EXECUTE 权限,过程虽能创建成功,但调用时会报 ERROR 1449: The user specified as a definer does not exist 或权限拒绝。
实操建议:
- 导出后先用
grep -n "DEFINER" mydb_routines.sql查看所有定义者 - 目标库执行
SELECT User,Host FROM mysql.user;确认用户是否存在;不存在就CREATE USER并赋权:GRANT EXECUTE ON mydb.* TO 'user'@'host'; - 更省事的做法是导入前全局替换:
sed -i 's/DEFINER=`[^`]*`@`[^`]*`/DEFINER=CURRENT_USER/g' mydb_routines.sql,让过程以当前登录用户为定义者 - 注意
CURRENT_USER是会话级的,确保你用有足够权限的账号登录再导入
MySQL 5.7 与 8.0 之间迁移要留意 sql_mode 兼容性
MySQL 8.0 默认启用严格模式(如 ONLY_FULL_GROUP_BY、STRICT_TRANS_TABLES),而 5.7 可能宽松。过程体里若有模糊分组、隐式类型转换或未声明的变量,导入后可能不报错,但运行时报 ERROR 1055 或逻辑异常。
实操建议:
- 导入前在目标库临时设宽松模式:
SET sql_mode = 'NO_ENGINE_SUBSTITUTION';(仅当前会话有效) - 导入完成后,逐个调用过程测试,观察是否触发警告或错误;可用
SELECT @@sql_mode;对比源库与目标库设置 - 过程内避免使用未初始化的变量,MySQL 8.0 对
DECLARE后未SET的变量更敏感 - 若过程含
JSON函数(如JSON_EXTRACT),确认目标版本支持——5.7.8+ 才有完整 JSON 支持,低版本会直接报语法错
用 mysql 命令行导入时别忽略字符集和连接参数
中文过程名、注释或内部字符串若出现乱码,大概率是客户端与服务端字符集不一致。常见现象是导入后 SHOW CREATE PROCEDURE 显示问号或截断,调用时报 ERROR 1300: Invalid utf8mb4 character string。
实操建议:
- 导出时显式指定字符集:
mysqldump --default-character-set=utf8mb4 -u root -p --routines mydb > mydb_routines.sql - 导入时也带上相同参数:
mysql --default-character-set=utf8mb4 -u root -p mydb - 检查目标库默认字符集:
SELECT DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME='mydb';,不匹配就ALTER DATABASE mydb CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci; - 避免用图形化工具(如 phpMyAdmin、Navicat)中转导入,它们可能静默修改换行符或编码,优先走命令行
过程迁移最麻烦的不是语法,而是隐式依赖:DEFINER 权限、SQL 模式、字符集、甚至系统变量(比如 max_sp_recursion_depth)。一次导完不等于能跑通,得真调用、真传参、真看日志。











