如何创建MySQL触发器自动记录数据变更

小枫君_6390

小枫君_6390

2026-09-24

685人浏览

原创

必须使用after触发器,因其能确保事务提交、主键生成和数据落地后再写日志,避免回滚导致审计失效;after中old/new代表最终值,配合json_object()结构化记录变化字段,审计表需规范设计字段类型与索引,且触发器内禁止查表、调过程或改业务表。

如何创建mysql触发器自动记录数据变更

必须用 AFTER 触发器,不能用 BEFORE —— 否则日志和实际数据不一致是大概率事件。

为什么只用 AFTER INSERT/UPDATE/DELETE

BEFORE 触发器里 OLDNEW 虽然可读,但事务还没提交:自增主键可能仍是 NULLAFTER INSERT 才确定),外键约束也可能未生效,更关键的是——事务若回滚,日志已写入,数据却没变,审计就失效了。
只有 AFTER 能确保变更已落库、主键已生成、事务上下文完整。

  • AFTER INSERT:只读 NEW.*,此时主键值已稳定
  • AFTER UPDATEOLD.*NEW.* 都可用,且都代表最终落地值
  • AFTER DELETEOLD.* 仍可读,即使触发级联删除,也能拿到被删行快照

JSON_OBJECT() 是构造日志值的唯一推荐方式

别拼字符串:CONCAT 遇到单引号、换行、NULL 就崩,且无法被下游解析为结构化数据。
JSON_OBJECT() 自动处理 NULL → JSON null,字段名必须用字符串字面量(如 'name'),不能写变量名。

MySQL
MySQL

编写正确的MySQL查询,避免字符集、索引和锁方面的常见陷阱。

下载
  • 只记录变化字段:比如只关心 status 变更,就只写 JSON_OBJECT('status', OLD.status, 'updated_at', NOW())
  • 全量记录也行,但字段要显式列出:JSON_OBJECT('id', NEW.id, 'name', NEW.name)
  • 字段类型必须匹配原表,否则插入日志表时会截断或报错 Data too long

审计表结构不能偷懒,字段设计决定后期能不能查

光存整行 JSON 看似省事,但没法索引、无法按字段统计、查起来慢得像翻纸书。真正能用的日志表至少含:

  • table_nameVARCHAR(64)):方便跨表统一查
  • row_id(类型严格匹配原表主键,比如 BIGINT):别用 VARCHAR 存数字 ID,否则关联查询性能崩
  • operationENUM('INSERT','UPDATE','DELETE')):比字符串节省空间,避免索引失效
  • old_value / new_valueJSON 类型):字段级差异,不是整行 dump
  • created_at(用 NOW(),别用 SYSDATE()):后者在事务中可能因延迟产生歧义
  • user_id(应用层传入,别用 CURRENT_USER()USER()):它们返回数据库账号,不是业务用户

触发器里禁止做三件事:查表、调过程、改其他业务表

触发器运行在主 DML 的临界路径上,任何额外开销都会直接拖慢业务 SQL。曾有案例在 AFTER UPDATESELECT ... JOIN user_profiles 补用户名,结果主表更新卡住,连接池耗尽。

  • 禁止 SELECT INTO、子查询、关联大表
  • 禁止调用含事务控制的存储过程(会报 Can't execute statement in trigger
  • 禁止在触发器里再 INSERT/UPDATE 其他业务表——容易引发循环触发或死锁
  • 日志表引擎必须用 InnoDB,保证与主表事务一致性

最易被忽略的点:一个表最多只能有一个 AFTER INSERT、一个 AFTER UPDATE、一个 AFTER DELETE 触发器;重复定义会直接报错 Can't create more than one trigger with the same action time and event for one table。线上高频表启用后,务必监控日志表写入 QPS 和磁盘增长,膨胀过快就得加归档策略。

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

2023.10.12

3743

8

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.27

791

4

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

2024.02.23

969

5

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

5541

10

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

2523

4

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

2024.04.07

5520

11

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

2024.04.29

7201

6

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

970

5

sql中删除一列的命令是什么
sql中删除一列的命令是什么

在sql中,使用alter table语句可以删除一列,语法为:alter table table_name drop column column_name。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

872

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL vs MySQL
PostgreSQL vs MySQL

共1课时 | 172人学习

使用phpenv集成环境安装极致CMS
使用phpenv集成环境安装极致CMS

共2课时 | 274人学习