当前位置:首页 > 文章列表 > 数据库 > MySQL > 使用 FOLLOWS 或 PRECEDES 明确同一事件多个触发器的先后关系

使用 FOLLOWS 或 PRECEDES 明确同一事件多个触发器的先后关系

来源:17golang原创 2026-10-13 06:13:23 0浏览 收藏

同一张表上有多个 BEFORE UPDATE 触发器时,MySQL 默认按创建顺序执行;如果业务要求“先规范化,再记录审计”,不要把希望寄托在建表脚本的排列上。创建后续触发器时,用 PRECEDES 已有触发器 或 FOLLOWS 已有触发器 把关系写进定义,并且只在相同事件、相同动作时机的触发器之间排序。

要点速览
  • 排序范围是同一张表上相同事件和相同动作时机的触发器,不是所有触发器的全局顺序。
  • PRECEDES 把新触发器放到指定触发器之前,FOLLOWS 放到之后。
  • 发布后用 SHOW CREATE TRIGGER 和 INFORMATION_SCHEMA.TRIGGERS 留下可复核的定义记录。

先固定触发器的事件与时机

我在维护订单表时,常见的拆分是:一个触发器把状态值规范化,一个记录更新时间,另一个根据行值更新派生字段。这几个动作如果都绑定在 BEFORE UPDATE,就处于同一排序组;BEFORE INSERT、AFTER UPDATE 即使作用于同一张表,也不应拿来和它们比较先后。

先把边界写成清单,再决定顺序:

判断项必须一致的内容不一致时
对象同一张表不能用 FOLLOWS/PRECEDES 互排
事件同为 INSERT、UPDATE 或 DELETE属于不同触发链
时机同为 BEFORE 或 AFTER属于不同触发链
MySQL orders 表中 BEFORE UPDATE 触发器可排序链与 INSERT、AFTER 分支边界结构说明图
图1:触发器作用域结构说明图,先按事件和时机划定可排序范围。

另外,BEFORE 触发器可以通过 SET NEW.col_name = value 修改即将写入的值,这正是“规范化”应放在前面的原因。AFTER 阶段行变化已经发生,不适合再改写 NEW。

用 FOLLOWS 或 PRECEDES 把顺序写进定义

下面的例子把三个动作拆开:先规范状态,再记录审计时间,最后计算摘要。每个代码块都保留中文注释,便于后续维护者知道排序关系不是偶然的创建顺序。

-- 先创建同一排序组中的第一个触发器,负责规范状态值
CREATE TRIGGER normalize_status
BEFORE UPDATE ON orders
FOR EACH ROW
SET NEW.status = LOWER(TRIM(NEW.status));

-- 明确放在 normalize_status 之后,避免审计动作读取未规范的状态
CREATE TRIGGER audit_changed_at
BEFORE UPDATE ON orders
FOR EACH ROW FOLLOWS normalize_status
SET NEW.changed_at = CURRENT_TIMESTAMP;

-- 明确放在 audit_changed_at 之后,最后计算依赖前面结果的摘要
CREATE TRIGGER rebuild_summary
BEFORE UPDATE ON orders
FOR EACH ROW FOLLOWS audit_changed_at
SET NEW.summary = CONCAT(NEW.status, ':', NEW.changed_at);

如果是后来发现某个新动作必须插到最前面,可以改用 PRECEDES normalize_status。关键字后面引用的是已经存在、且属于同一事件和时机的触发器名;它不是任意注释,也不是给触发器起新的排序编号。

MySQL FOLLOWS 和 PRECEDES 触发器顺序声明及 SHOW CREATE TRIGGER 复核路径结构说明图
图2:FOLLOWS/PRECEDES 排序结构说明图,顺序声明与复核动作一一对应。

发布后用定义和最小更新复核

不要只看迁移文件的文本顺序。上线后先查看关键触发器定义,再用一行测试数据检查最终字段是否符合预期:

-- 读取定义,确认排序子句和目标表没有被误改
SHOW CREATE TRIGGER audit_changed_at;
SHOW CREATE TRIGGER rebuild_summary;

-- 从元数据表按名称列出同表触发器,作为维护清单
SELECT TRIGGER_NAME, EVENT_MANIPULATION, ACTION_TIMING, ACTION_STATEMENT
FROM INFORMATION_SCHEMA.TRIGGERS
WHERE TRIGGER_SCHEMA = DATABASE()
  AND EVENT_OBJECT_TABLE = 'orders'
ORDER BY ACTION_TIMING, EVENT_MANIPULATION, TRIGGER_NAME;

-- 用事务包住最小更新,便于发现字段依赖顺序不对时回滚测试数据
START TRANSACTION;
UPDATE orders SET status = ' PAID ' WHERE id = 1001;
SELECT id, status, changed_at, summary FROM orders WHERE id = 1001;
ROLLBACK;

这里的查询结果适合做人工复核清单,但不要把按名称排序的查询结果误当成执行顺序证明;真正的排序关系应以每个触发器的定义为准。若某个 BEFORE 触发器报错,触发它的整条语句会失败;对事务表而言,语句产生的改动也会回滚。

重建和维护时的三个边界

  1. 删除被引用的触发器前先改链路。 如果后续部署仍声明 FOLLOWS 或 PRECEDES 指向已删除对象,迁移脚本就会失去明确的参照。
  2. 同一动作不要拆成隐式依赖。 让摘要触发器依赖审计触发器的字段时,应在定义和文档中说明依赖;否则单独重建其中一个触发器容易改变行为。
  3. 多行 UPDATE 也按行触发。 触发器主体是 FOR EACH ROW,测试时要覆盖多行更新和失败回滚,不能只验证一行的偶然结果。

常见问题

FOLLOWS 和 PRECEDES 能不能跨 BEFORE、AFTER 使用?

不能。它们用于同一表、同一事件、同一动作时机中的已有触发器;跨组时应重新设计链路。

不写排序子句时,顺序是不是永久稳定?

默认按创建顺序执行,但重建、迁移和恢复可能改变创建历史。需要长期稳定的依赖,应显式写出 FOLLOWS 或 PRECEDES。

为什么查 INFORMATION_SCHEMA 后还要看 SHOW CREATE TRIGGER?

元数据表适合盘点对象和绑定事件,SHOW CREATE TRIGGER 更适合确认具体定义中的排序子句,两者用途不同。

把触发器看成一条有边界的数据处理链:先确认同组,再声明相邻关系,最后用定义和事务测试复核。这样新增审计或派生逻辑时,顺序就不会只存在于某次部署的时间线上。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
定位底层表变更导致的视图失效,并用 CHECK TABLE 检查定义问题定位底层表变更导致的视图失效,并用 CHECK TABLE 检查定义问题
上一篇
定位底层表变更导致的视图失效,并用 CHECK TABLE 检查定义问题
区分 BEFORE 触发器修改 NEW 与 AFTER 触发器只能读取行值的行为
下一篇
区分 BEFORE 触发器修改 NEW 与 AFTER 触发器只能读取行值的行为
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    450次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    520次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    535次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    480次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    304次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码