触发器查不到、删不掉?先确认它真在那儿
很多“管理混乱”其实始于根本不知道触发器是否存在或定义是否生效。MySQL 不像存储过程那样能用
SHOW PROCEDURES一键扫清,必须主动查。 用
SHOW TRIGGERS查当前库所有触发器:
SHOW TRIGGERS;按表过滤更实用:
SHOW TRIGGERS LIKE 'orders';看完整定义(尤其怀疑语法被静默截断时):
SHOW CREATE TRIGGER update_order_log;如果返回空,不是“没生效”,而是压根没创建成功——检查
CREATE TRIGGER是否执行过,以及有没有被事务回滚或权限拦截
删错触发器或误删后无法恢复?必须加 IF EXISTS
线上环境执行
DROP TRIGGER trigger_name报错
ERROR 1360 (HY000): Trigger does not exist并不可怕;可怕的是没加防护就批量删,结果把关键审计触发器干掉了。 永远用
IF EXISTS保底:
DROP TRIGGER IF EXISTS before_user_insert;跨库删除要显式指定 schema:
DROP TRIGGER IF EXISTS sales_db.audit_customer_update;别依赖“记得住名字”——用
information_schema.triggers导出清单再操作:
SELECT trigger_name, event_object_table, action_timing, event_manipulation FROM information_schema.triggers WHERE trigger_schema = 'prod_db';
触发器越来越多,命名和职责开始打架?立刻建立命名与隔离规范
当出现
trg_orders_after_insert_v2、
trg_orders_after_insert_audit、
trg_orders_after_insert_sync并存时,说明逻辑已失控。MySQL 触发器不支持注释字段,命名就是唯一文档。 强制命名格式:
trg_[表名]_[时机]_[事件]_[用途],例如:
trg_products_before_update_price_check禁止多个触发器监听同一事件+同一表——合并逻辑,或用条件分支(
IF OLD.status != NEW.status THEN ...)替代 日志类、校验类、同步类触发器必须分表处理:校验放
BEFORE,日志写独立
trigger_log表,同步走应用层或事件调度器,绝不让一个触发器干三件事
改了表结构,触发器突然报错?重点检查 NEW/OLD
引用和 SQL 模式
ERROR 1327 (42000): Undeclared variable: NEW.price或隐性数据截断,往往不是触发器坏了,而是底层变了它还不知道。 每次
ALTER TABLE后,手动验证涉及的触发器:
INSERT INTO products (name) VALUES ('test'); 看是否抛错
启用严格模式防“静默失败”:SET sql_mode = 'STRICT_TRANS_TABLES';这能让
NEW.xxx访问不存在字段、字符串超长等立刻暴露 避免在触发器里拼接动态列名——
NEW和
OLD是固定上下文,不支持变量列引用;真要泛化处理,得上存储过程+预编译,但那已超出触发器适用范围 管理混乱的本质,是把触发器当成了“能塞多少逻辑就塞多少”的黑盒。它只适合做轻量、确定、原子的事。一旦发现需要加锁、重试、异常分支或跨表强一致性保障,就该停手——那已经不是触发器该管的地界了。
