应导出时勾选“Remove DEFINER and SQL SECURITY”,或手动用正则删除DEFINER=[^]+@[^]+及SQL SECURITY DEFINER;还原后需显式授予EXECUTE权限并FLUSH PRIVILEGES。
DEFINER 用户在目标库根本不存在
还原时存储过程报错 error 1227 (42501): access denied,大概率不是权限没给够,而是 definer 指向了一个目标库压根没有的用户。比如备份里是 create definer=`app_user`@`192.168.1.%` procedure ...,但目标 mysql 实例里只有 app_user@localhost,甚至这个用户完全没创建过。navicat 还原过程不会自动降级或替换 definer,遇到就直接中断建过程语句。
还原前没清理 DEFINER,还原后也别硬改 CURRENT_USER
常见误区是导出 SQL 后手动把所有 DEFINER=`xxx`@`yyy` 替成 CURRENT_USER。这反而更危险:还原时会话用户(比如你用 root 连的)执行 CALL 没问题,但其他应用账号调用时,CURRENT_USER 变成它自己,很可能没跨库或写表权限,立刻报错。
- 正确做法:导出时就在 Navicat 的 Backup Database → 高级选项里勾选
Remove DEFINER and SQL SECURITY - 已拿到 SQL 文件?用正则全局删掉
DEFINER=`[^`]+`@`[^`]+`,再删紧跟着的SQL SECURITY DEFINER(注意空格) - 千万别留
SQL SECURITY INVOKER——它会让执行时按调用者权限检查,而多数业务账号没那么高权限
还原后没补存储过程执行权限
Navicat 还原只跑 DDL 和 DML,不会帮你执行 GRANT EXECUTE ON PROCEDURE db_name.sp_name TO 'user'@'%'。哪怕你用 root 还原完,普通账号照样 CALL 失败,错误还是 Access denied。
- 还原完成后,立刻用高权限账号连上去补授权:
GRANT EXECUTE ON PROCEDURE `target_db`.`sp_name` TO 'app_user'@'%'; - 如果存储过程内部访问了其他库的表,还得额外给
SELECT/INSERT等权限,仅EXECUTE不够 - MySQL 8.0+ 下,改完权限记得
FLUSH PRIVILEGES;,否则可能缓存生效延迟
Navicat 还原不维护会话上下文,DEFINER 绑定是静态的
很多人以为“我用 root 还原,那 DEFINER 自动变成 root”,这是错的。Navicat 还原就是把 SQL 文件当普通脚本一条条执行,CREATE PROCEDURE 语句里的 DEFINER 是硬编码进语句的,跟当前登录用户无关。所以还原前不处理 DEFINER,还原后它就永远卡在那个不存在的用户上,删都删不掉——除非 DROP PROCEDURE 再重建。
最稳妥的路径:备份阶段就去掉 DEFINER,还原后按需授 EXECUTE 权限,别指望还原工具替你兜底。











