mysqldump默认不导出触发器和存储过程,必须显式添加--triggers和--routines参数;仅加其一会导致对应对象缺失,导入后功能完全丢失。

mysqldump 默认不导出触发器和存储过程,必须显式加参数,否则导入后功能完全丢失。
mysqldump 必须加 --triggers 和 --routines 才能导出触发器与存储过程
默认情况下 mysqldump 只导出表结构、数据、索引、视图,--triggers 和 --routines 是两个独立开关,缺一不可:
-
--triggers:导出所有触发器(含DEFINER信息) -
--routines:导出存储过程和函数(不含触发器) - 只加
--routines不加--triggers→ 触发器被跳过 - 用
-B(即--databases)时,--triggers仍需手动指定,它不会自动启用
正确命令示例:mysqldump -u root -p --triggers --routines --databases mydb > backup.sql
导入时 DEFINER 权限问题导致失败
导出的 CREATE TRIGGER 或 CREATE PROCEDURE 语句里通常带 DEFINER=`user`@`host`,若目标库不存在该用户,或权限不足,会报错:ERROR 1418 (HY000): This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA 或更直接的 Access denied。
- 最稳妥做法:导出后用 sed 或编辑器全局替换
DEFINER=.*?@.*?为DEFINER=CURRENT_USER - 或在导出时加
--skip-definer(MySQL 5.7.6+ 支持),但注意这会丢失原始定义者上下文 - 导入前确保目标用户有
TRIGGER和EXECUTE权限
跨版本迁移时语法兼容性风险
MySQL 5.7 与 8.0 的触发器/存储过程语法差异虽小,但容易踩坑:
- MySQL 8.0 默认开启
sql_mode=STRICT_TRANS_TABLES,触发器内插入非法值(如超长字符串)会直接中断事务,5.7 可能仅警告 -
UUID()、NOW()在某些 binlog 格式(如 STATEMENT)下,8.0 要求显式声明DETERMINISTIC,否则创建失败 - 触发器中引用的表名若含数据库前缀(如
mydb.users),需确认目标库名一致,否则报Table doesn't exist - 建议迁移前在目标版本执行
SHOW CREATE TRIGGER trigger_name检查语法,并用mysql --version核对两端版本
大库迁移时避免锁表与超时
触发器和存储过程本身不增大 dump 文件体积,但它们依赖的表结构和数据量会影响整体导出耗时;更重要的是,导入过程中若触发器逻辑复杂(如含 UPDATE 多张表、调用函数等),可能拖慢 source backup.sql 执行速度,甚至触发 wait_timeout 或 max_allowed_packet 限制。
- 导入前临时禁用触发器(仅限测试/预演):
SET @OLD_SQL_MODE=@@SQL_MODE; SET SQL_MODE='NO_AUTO_VALUE_ON_ZERO';,但生产环境不建议跳过触发逻辑 - 增大客户端限制:
mysql -u root -p --max-allowed-packet=512M --net-buffer-length=1M - 对超大表,可先用
--no-create-info --no-data分离结构与数据,再单独处理触发器/过程的 DDL 部分
真正容易被忽略的是:触发器和存储过程的执行上下文依赖当前数据库(USE db_name),而 mysqldump --databases 输出的 SQL 中每段 CREATE 前都有 USE 语句——但如果手动拆分文件或用管道导入,USE 可能失效,导致对象建到错误库中。











