mysql触发器不适合生产级审计,因其无法捕获truncate、load data、ddl、逻辑备份恢复及从库复制等操作,且易导致事务失败和性能瓶颈;官方推荐使用audit_log插件,它在连接层记录全量事件,覆盖登录、sql执行及结果状态。

MySQL 触发器不适合做生产级审计,它只能作为临时补救或低负载场景下的辅助手段。真正可靠的审计必须依赖 MySQL 自身的通用日志(general_log)、审计插件(如 audit_log)或外部代理层(如 ProxySQL + 日志捕获),否则极易漏记录、拖慢性能、甚至导致事务失败。
触发器审计会 silently 丢失哪些操作
触发器只在 INSERT/UPDATE/DELETE 语句执行时触发,但以下关键行为完全绕过它:
-
TRUNCATE TABLE—— 不走触发器,不记 binlog(在 ROW 格式下也不触发) -
LOAD DATA INFILE—— 批量导入默认不触发行级触发器(取决于版本和 sql_mode) - DDL 操作(
ALTER/DROP/CREATE)—— 触发器对结构变更无感知 - 通过
mysqldump --single-transaction或mysqlpump的逻辑备份恢复 —— 属于客户端重放,可能跳过触发器逻辑 - 从库上的复制线程写入 —— 即使主库触发了,从库默认不重新触发(除非显式设置
log_bin_trust_function_creators=1且函数被标记为DETERMINISTIC,但依然不可靠)
audit_log 插件才是官方推荐的审计路径
MySQL 5.6+ 官方企业版自带 audit_log 插件,社区版可通过 MariaDB 的 server_audit 插件或 Percona Server 的 audit_log 替代。它记录的是连接层事件,覆盖完整:
- 登录/登出(含用户名、IP、时间戳)
- 所有 SQL 语句(包括 DDL、
SET、USE等) - 执行结果状态(
status字段标识成功/权限拒绝/语法错误等) - 支持 JSON 或 XML 格式输出,可直接对接 ELK 或 Syslog
启用方式极简:
INSTALL PLUGIN audit_log SONAME 'audit_log.so';再配置
audit_log_format 和 audit_log_policy 即可。注意:该插件会轻微增加连接开销,但远低于触发器对 DML 的阻塞影响。
触发器审计的典型性能陷阱
每个触发器都运行在原事务上下文中,意味着:
- 审计表写入失败(如磁盘满、锁冲突、字段类型不匹配)会导致整个业务事务回滚 ——
INSERT INTO orders失败仅仅因为INSERT INTO audit_log报错 - 高并发下审计表成为热点,
INSERT ... SELECT ... FROM information_schema.PROCESSLIST这类常用“取客户端信息”操作会加剧元数据锁争用 - 触发器中调用
NOW()或USER()是安全的,但调用自定义函数或访问其他表(尤其大表 JOIN)极易引发死锁 - MySQL 8.0 后虽支持触发器内事务控制(
GET DIAGNOSTICS),但无法 rollback 外部事务,只能 abort 当前触发器逻辑 —— 审计失败仍无补救机制
真正的审计设计不是“要不要记”,而是“谁来记、在哪记、记多少、怎么查”。触发器连“谁来记”都答不上来 —— 它依赖业务 SQL 路径,而真实系统里 ORM、中间件、定时任务、离线脚本根本不会走你写的那几个触发器。










