MySQL 8.0触发器报错核心三点:一是旧时间类型格式残留需ALTER TABLE FORCE转换表格式;二是DEFINER用户不存在或权限不足须核查并重建;三是log_bin_trust_function_creators未启用或函数非确定性导致ERROR 1418。

直接修复触发器报错,核心就三点:先查清错在哪一类,再针对性改表、改definer、改函数调用方式,而不是盲目删重建。
触发器创建时报ERROR 1064或SHOW CREATE TRIGGER返回乱码
这是旧时间类型格式残留导致的,本质是表没完成磁盘格式升级,触发器引用了5.5二进制存储的DATETIME/TIMESTAMP字段。
- 先确认问题表:
SELECT table_schema,table_name,column_name,column_type FROM information_schema.columns WHERE column_type LIKE '%5.5 binary format%'; - 对每张结果表执行强制转换:
ALTER TABLE db_name.table_name FORCE;(注意:该操作会重建表,需评估锁表时间) - 转换完成后,再用
SHOW CREATE TRIGGER导出触发器定义,重新CREATE TRIGGER——此时语法才能被8.0正确解析
服务启动失败或触发器静默失效,日志报ERROR MY-010952
MySQL 8.0严格校验DEFINER用户是否存在且有TRIGGER权限,而5.7允许指向已删除账户(如DEFINER='zabbix'@'localhost')。
- 查出所有触发器的definer:
SELECT TRIGGER_NAME, DEFINER FROM information_schema.TRIGGERS WHERE TRIGGER_SCHEMA = 'your_db'; - 检查对应用户是否还存在:
SELECT User,Host FROM mysql.user WHERE User = 'zabbix'; - 若用户已删,不要留空
DEFINER,也不要用不存在账号;应显式指定当前有效管理用户,例如:CREATE TRIGGER ... DEFINER = 'root'@'localhost' ... - 重建前建议临时启用:
SET GLOBAL log_bin_trust_function_creators = 1;,避免因函数调用再触发其他错误
触发器执行时报ERROR 1418,尤其调用自定义函数时
不是函数本身写错了,而是MySQL 8.0默认log_bin_trust_function_creators=0,拒绝非确定性函数进入binlog——而NOW()、RAND()、子查询都算非确定性。
- 检查函数声明是否含
DETERMINISTIC、NO SQL或READS SQL DATA——缺一不可 - 若函数确实非确定性(比如必须用
NOW()),则必须开启信任:SET GLOBAL log_bin_trust_function_creators = 1;(配置文件中也要加log_bin_trust_function_creators=1) - 注意:仅设
log_bin_trust_function_creators=1还不够,函数定义里仍要显式声明DETERMINISTIC,否则8.0仍会拒载
多个同类型触发器报“same trigger event and action time already exists”
这说明你还在用5.6逻辑判断问题——MySQL 5.7.2+已支持多触发器,但必须显式用FOLLOWS/PRECEDES声明顺序,否则8.0直接拒绝第二条创建。
- 已有触发器
t1_after_update,新增必须写:CREATE TRIGGER t2_after_update AFTER UPDATE ON t FOLLOWS t1_after_update ... -
FOLLOWS和PRECEDES只接受已存在触发器名,不能指向不存在的或自己 - 触发器名必须全局唯一,不能和函数、存储过程重名,否则
CREATE TRIGGER会报ERROR 1304
最容易被忽略的是:即使修复了语法和definer,如果表上还有旧版虚拟列(比如用json_extract()生成的STORED列),再在上面建索引或让触发器引用它,依然可能触发隐式类型转换失败。务必逐个验证触发器里涉及的所有列、函数、索引定义是否符合8.0语义。


















