mysqldump 不支持按名导出单个存储过程或触发器,必须用 show create procedure/show create trigger 手动提取(需补 delimiter),或全量导出后 grep/sed 精确截取,mysqlpump --routines --exclude-tables=% 可导全部 routine 但无法指定个别对象。

mysqldump 没有原生支持“只导出某几个存储过程”或“只导出某几个触发器”的参数。你不能用 --routines 或 --triggers 加个过滤条件就精准命中单个对象——它们都是全库/全表级开关。
但实际运维中确实需要这种粒度,比如灰度发布前备份变更的触发器、审计时提取某个关键过程定义。下面给出几种**真实可行、不依赖第三方工具**的操作路径。
用 SHOW CREATE 手动提取单个对象定义
这是最直接、权限要求最低、兼容性最好的方式,适用于任意 MySQL 版本(5.7+ 和 8.0+ 都行),且不依赖系统表访问权限。
执行 SHOW CREATE PROCEDURE 或 SHOW CREATE TRIGGER 返回的是可执行 SQL,但要注意两点:
-
SHOW CREATE不输出DELIMITER,如果过程体里含分号(几乎必然),直接source会报错;必须人工补上DELIMITER $$和结尾$$ - 触发器名必须带库名前缀:
SHOW CREATE TRIGGER mydb.t_audit_insert;,否则报错ERROR 1360 (HY000): Trigger does not exist - 输出结果可重定向保存:
mysql -u root -p -e "SHOW CREATE PROCEDURE mydb.calc_total;" > proc_calc_total.sql
用 mysqldump 全量导出后 grep 提取
适合批量操作或写脚本,前提是已确认备份文件里确实含目标对象(即已加 --routines 和 --triggers)。
注意:grep 模式要足够精确,避免误匹配注释或函数体内的字符串:
- 提取所有存储过程:
grep -A 50 "^CREATE DEFINER.*PROCEDURE" backup.sql | grep -B 50 "^$$" > procedures.sql - 提取特定触发器:
grep -A 30 "CREATE DEFINER.*TRIGGER `t_user_log`" backup.sql > trigger_t_user_log.sql - 更稳妥的做法是先用
sed -n '/^CREATE DEFINER.*TRIGGER `t_name`/,/^$$/p' backup.sql,它能跨行匹配完整定义块
用 mysqlpump(MySQL 5.7+)按名排除表、只留 routine
mysqlpump 是 mysqldump 的继任者,支持更细粒度的对象筛选,但它仍不支持“只导某几个 routine”,只能做到“导全部 routine + 排除所有表”。
命令示例:
mysqlpump --user=root --password --routines --exclude-tables=% mydb > routines_only.sql-
--exclude-tables=%表示排除所有表(包括视图),但保留 routine、trigger、event 等逻辑对象 - 该方式导出的触发器仍绑定在原表上,若目标库表结构缺失,导入会失败;需确保表已存在或提前建好
- 注意:8.0.23+ 默认启用
--skip-definer,无需额外处理 DEFINER 权限问题
为什么不能靠 --ignore-table 或 --where 实现?
这两个参数只作用于**表数据和结构**,对 routine 和 trigger 完全无效:
-
--ignore-table=mydb.users只跳过users表的建表语句和数据,但该表上的触发器仍会被--triggers导出 -
--where只影响 SELECT 数据的 WHERE 条件,routine 和 trigger 没有“行”的概念,压根不参与该机制 - 试图组合
--skip-triggers --routines并期望“只导过程不导触发器”是徒劳的——--skip-triggers是全局禁用,不是选择性关闭
SHOW CREATE + 手动补 DELIMITER 这一步。自动化脚本可以封装这个流程,但核心逻辑绕不开——因为 MySQL 本身没提供“按名导 routine”的 SQL 接口,information_schema.ROUTINES 只存元信息,不存完整定义。











