
MySQL 迁移时触发器消失,是因为 mysqldump 默认跳过
导出 SQL 时触发器没进文件,不是你漏了参数,而是 MySQL 5.7+ 版本默认启用 --skip-triggers 行为——哪怕你什么都没写,它也自动跳过。结果就是 dump 文件里压根没有 CREATE TRIGGER 语句,一导入,业务逻辑直接断档。
实操建议:
- 导出必须显式加
--triggers:例如mysqldump --triggers -u root -p mydb > backup.sql - 导出后立刻验证:用
grep -n "CREATE TRIGGER" backup.sql确认语句真实存在 - 别信“我加了 --all-databases 就够了”——它不自动包含触发器,仍受 --skip-triggers 影响
SQL Server 触发器迁到国产库,TOP/GETDATE/TRY...CATCH 怎么办
SQL Server 的触发器大量依赖 T-SQL 特有语法,比如 TOP 1、GETDATE()、ISNULL()、TRY...CATCH 块,这些在标准 PostgreSQL 或 MySQL 中根本不可执行。金仓等国产库虽支持 sql_compatibility = 'SQLSERVER' 模式,但仅限于基础语法层;一旦触发器里嵌套了游标、临时表 #temp 或引用了 @@ERROR 这类全局变量,就会编译失败。
实操建议:
- 先关兼容模式跑一遍:用
SET sql_compatibility = 'STRICT';暴露所有隐性不兼容点 - 逐个替换系统函数:
GETDATE()→CURRENT_TIMESTAMP,ISNULL(a,b)→COALESCE(a,b) -
TRY...CATCH必须拆:用EXCEPTION WHEN OTHERS THEN(PostgreSQL 风格)或改用应用层捕获,MySQL 8.0+ 也不支持原生 TRY CATCH - 避免
SELECT TOP N写法:改用LIMIT N(PostgreSQL/MySQL)或显式子查询 +ROWNUM(Oracle 兼容路径)
导入时报 ERROR 1359 或 ERROR 1449,说明 DEFINER 和名字冲突了
ERROR 1359 (HY000): Trigger already exists 是目标库已有同名触发器,而 dump 文件又执行了 CREATE TRIGGER;ERROR 1449 (HY000): The user specified as a definer ('xxx'@'%') does not exist 则是源库的 DEFINER 用户在新库不存在——这两类错误在跨版本、跨厂商迁移中高频出现,且不会跳过,直接中断整个导入流程。
实操建议:
- 导入前清空目标库触发器:
SELECT CONCAT('DROP TRIGGER ', TRIGGER_NAME, ';') FROM information_schema.TRIGGERS WHERE TRIGGER_SCHEMA = 'mydb';生成并执行结果 - 不要用
DROP DATABASE后重建:某些触发器绑定在系统表或跨库对象上,删库不等于清干净 - 手动替换 DEFINER:用
sed -i "s/DEFINER=`.*`@`.*/DEFINER=CURRENT_USER/g" backup.sql(注意 CURRENT_USER 必须有权限) - MySQL 不支持
CREATE OR REPLACE TRIGGER,必须先删后建,脚本里得保证顺序
触发器创建成功但运行时报 ERROR 1362,说明字段或函数已失效
最危险的情况是:导入时一切顺利,SHOW TRIGGERS 也能看到,但第一次 INSERT/UPDATE 就报 ERROR 1362 (HY000): Updating of OLD row is not allowed in after trigger 或静默跳过逻辑。原因通常是触发器里引用了被重命名的字段(如 OLD.user_id → 新表叫 OLD.uid),或用了已废弃函数(如 MySQL 8.0 废弃的 ENCRYPT()),这类问题不会在 CREATE 阶段暴露,只在运行时炸。
实操建议:
- 逐行比对触发器定义和目标表结构:
DESCRIBE target_table;看字段名、类型、是否允许 NULL - 禁用触发器再测试:
ALTER TABLE t DISABLE TRIGGER ALL;(PostgreSQL)或注释掉CREATE TRIGGER后手动模拟逻辑 - 旧库用的
OLD.col/NEW.col在新库可能不支持隐式类型转换,显式加CAST(OLD.col AS CHAR) - 涉及 JSON 字段的触发器,MySQL 8.0+ 的
JSON_EXTRACT()在 5.7 下不存在,得降级为字符串截取或提前预处理










