mysqldump 不加 --routines 不会导出存储过程和函数,因其属数据库级对象,需配合 --databases 或库名使用;还需确保用户有 mysql.proc(5.7)或 mysql.routines/parameters(8.0+)的 SELECT 权限,并建议加 --skip-definer 避免恢复失败。

mysqldump 不加 --routines 就不会导出存储过程
默认情况下,mysqldump 只导出表结构和数据,CREATE PROCEDURE 和 CREATE FUNCTION 语句完全不会出现在备份文件里。你执行完恢复后,调用 CALL my_proc() 会直接报错 PROCEDURE db.my_proc does not exist。
根本原因不是权限或版本问题,而是设计如此:MySQL 把存储过程、函数、事件、触发器都归为“routine”,需要显式启用导出开关。
-
--routines是必须加的参数,没有缩写,也不能用-R(那是--replace) - 它只控制存储过程和函数,不包含触发器(需额外加
--triggers)和事件(需--events) - 即使数据库里只有 1 个存储过程,不加这个参数,dump 文件里也绝不会有
DELIMITER或CREATE PROCEDURE
加了 --routines 还没导出?检查用户权限
就算参数写对了,mysqldump 也可能静默跳过 routine 导出——典型表现是 dump 文件里有表,但没任何 CREATE PROCEDURE,且无报错提示。
这是因为 mysqldump 需要 SELECT 权限访问 mysql.proc 表(MySQL 5.7)或 mysql.routines(8.0+),而普通应用账号通常没这个权限。
- 临时解决:用
root或带SELECT ON mysql.*的账号执行 dump - 最小权限方案:给备份账号授
SELECT权限到mysql.proc(5.7)或mysql.routines+mysql.parameters(8.0) - 注意:MySQL 8.0 默认关闭
mysql库的 SELECT 权限继承,GRANT SELECT ON *.*不自动覆盖系统库
--routines 必须和 --databases 或指定库名一起用
单独 dump 某张表时加 --routines 是无效的。比如 mysqldump -u u -p db1 t1 --routines,输出里依然没有存储过程。
因为 routine 是数据库级别的对象,不是表级的。mysqldump 只在导出整个库(或多个库)时才扫描并注入 routine 定义。
- 正确写法:
mysqldump -u u -p --routines --databases db1 - 或:
mysqldump -u u -p --routines db1(等价于--databases db1) - 错误写法:
mysqldump -u u -p --routines db1 t1—— 此时--routines被忽略 - 如果要 dump 多个库并含 routine,必须用
--databases db1 db2,不能写成db1 db2
导出内容里有 DEFINER,恢复时容易失败
mysqldump 默认在 CREATE PROCEDURE 前加上 DEFINER=`user`@`host`。如果目标库没有这个用户,或者 host 不匹配(比如 dump 里是 DEFINER=`dev`@`localhost`,但恢复环境只允许 `dev`@`%`),就会报错 Access denied; you need (at least one of) the SUPER privilege(s) 或直接跳过创建。
- 安全做法:加
--skip-definer,让 dump 文件用DEFINER=CURRENT_USER替代,恢复时以当前登录用户身份创建 routine - 如果必须保留原 DEFINER,得先在目标库创建对应用户,且 host 要精确匹配(
localhost≠127.0.0.1) - MySQL 8.0.16+ 支持
--set-gtid-purged=OFF配合 routine 导出,但 GTID 和 DEFINER 冲突仍常见,别指望自动绕过
routine 导出看着就一个参数,但权限、作用域、DEFINER 三处全卡住就白忙活。尤其跨环境迁移时,--skip-definer 几乎是必选项,否则凌晨两点对着报错发呆就是常态。


















