MySQL 5.7.6+可用--skip-definer跳过导出DEFINER子句,但需配合--routines;老版本或需精细控制时可用sed清理;导入前可能需设log_bin_trust_function_creators=1避免1418错误。

导出时直接跳过DEFINER(MySQL 5.7.6+)
MySQL 5.7.6 起支持 --skip-definer 参数,它会让 mysqldump 在生成 CREATE PROCEDURE 语句时不写入 DEFINER=... 子句,等效于隐式使用 SQL SECURITY DEFINER 但不绑定具体用户。
实操建议:
- 必须配合
--routines使用,否则过程根本不会被导出 - 命令示例:
mysqldump -u root -p --routines --skip-definer mydb > routines_clean.sql - 该参数只影响 routine(过程/函数)和 trigger 的输出,不影响视图或事件
- 注意:
--skip-definer不会修改 SQL SECURITY 模式,只是删掉定义者,运行时仍按DEFINER语义执行——但因无显式用户,实际降级为调用者权限(即SQL SECURITY INVOKER行为)
导出后用sed批量清除DEFINER(兼容所有版本)
对老版本 MySQL 或需要更精细控制的场景,导出后再清理最稳妥。DEFINER 总是出现在 CREATE PROCEDURE 或 CREATE FUNCTION 行开头,格式固定。
实操建议:
- 先确认是否真有
DEFINER:grep -n "DEFINER=" routines.sql - 全局替换为当前用户(推荐):
sed -i 's/DEFINER=`[^`]*`@`[^`]*`/DEFINER=CURRENT_USER/g' routines.sql - 完全删除(等效于
SQL SECURITY INVOKER):sed -i 's/DEFINER=`[^`]*`@`[^`]*`[[:space:]]*//g' routines.sql - 注意 Windows 下用
gsed或 PowerShell 替代;macOS 的sed -i ''语法不同,别漏空字符串
导入前临时放宽权限限制(绕过1418错误)
即使没 DEFINER,MySQL 8.0+ 导入函数时仍可能报 ERROR 1418,因为 log_bin_trust_function_creators 默认关闭。这不是导出问题,但常被误认为导出失败。
实操建议:
- 目标库执行:
SET GLOBAL log_bin_trust_function_creators = 1; - 该设置仅对当前会话有效?错,它是 GLOBAL 级别,但需 SUPER 权限;重启后失效,生产环境建议写入
my.cnf - 仅函数受影响,存储过程不受此参数约束
- 如果无法改全局变量,只能在过程体里补全
DETERMINISTIC/NO SQL等特性声明
为什么不能靠 mysqldump 自动处理DEFINER?
mysqldump 本质是读取元数据表(mysql.proc 或 mysql.routines)拼 SQL,而 DEFINER 是这些表里的原始字段值。它不判断目标环境是否存在该用户,也不做上下文适配。
容易踩的坑:
- 用
--skip-definer导出后,若过程里有SELECT ... INTO @var这类依赖定义者权限的操作,运行时可能因权限不足静默失败 - 用
sed替换时漏掉触发器里的DEFINER(--triggers导出的触发器也带该子句) - 导出时用了
--databases,但CREATE DATABASE语句在文件开头,sed可能误删其他行里的`符号
真正关键的不是“怎么去掉”,而是“去掉之后谁来执行、以什么权限执行”——这得看过程体里有没有跨库查询、动态 SQL 或 EXECUTE IMMEDIATE 类操作。动手前先 SHOW CREATE PROCEDURE xxx\G 看一眼实际定义,比死盯参数有用得多。


















