mysql企业版audit_log插件仅记录执行成功的sql语句,不捕获失败操作、flush privileges、直接修改系统表等绕过sql接口的行为,且需手动加载并配置audit_log_policy=all、audit_log_format=json等参数方可生效。

MySQL企业版 audit_log 插件能记录“所有变更”——但前提是明确“变更”指什么:它只记录执行成功的 SQL 语句,不记录失败操作、不解析语义、不捕获 FLUSH PRIVILEGES 或直接改系统表等绕过 SQL 接口的行为。
确认 audit_log 插件已加载且可用
企业版 audit_log 是动态插件,不是默认启用的。必须先验证是否就位:
- 执行
SHOW PLUGINS;,查找audit_log行,状态为ACTIVE - 若无结果,需手动加载:
INSTALL PLUGIN audit_log SONAME 'audit_log.so';(路径依赖安装包,常见于/usr/lib/mysql/plugin/) - 加载失败常见原因:
audit_log.so文件缺失、权限不足、MySQL 版本不匹配(仅限 MySQL Enterprise Edition 5.7+ 或 8.0.25+ 社区版特供)
配置 audit_log_policy 和日志格式
插件默认策略是 ALL,但实际生效取决于你是否在配置中显式指定。关键配置项必须写入 my.cnf 并重启(或用 SET PERSIST 动态设置,8.0.23+ 支持):
-
audit_log_policy = ALL:捕获连接、查询、退出三类事件;若只需 DDL/DML,可设为QUERIES,但会漏掉CONNECT类事件 -
audit_log_format = JSON:强烈推荐,字段结构清晰(含timestamp、user、query、status),便于后续解析;OLD格式已弃用 -
audit_log_file = /var/lib/mysql/audit.log:确保目录存在且mysql用户有写权限(chown mysql:mysql /var/lib/mysql) - 不建议设
audit_log_strategy = ASYNCHRONOUS:虽降低性能影响,但崩溃时可能丢失最后几条日志
audit_log 能捕获哪些“变更”,又漏掉哪些
它记录的是 COM_QUERY 协议层的原始语句,不是逻辑变更。这意味着:
- ✅ 记录:
GRANT SELECT ON db.t TO 'u'@'%'、ALTER TABLE t ADD c INT、UPDATE t SET x=1 WHERE id=1 - ❌ 不记录:
FLUSH PRIVILEGES(无 SQL 执行,只是内存重载)、UPDATE mysql.user SET ...(虽是 DML,但插件默认不审计系统库,且语义难识别) - ⚠️ 模糊记录:
CALL set_perms('u', 'db')—— 日志里只有 CALL 语句,看不到内部执行的 GRANT;需配合源码或存储过程定义人工还原 - ⚠️ 不记录失败语句:
DROP TABLE nonexistent报错ERROR 1051,audit_log 完全不落盘;而general_log会记(但无 status 字段)
解析 audit.log 并提取有效变更
JSON 格式日志每行一条记录,可用标准工具快速过滤。例如,提取所有 DDL 和权限变更:
grep -E '"event":"query".*"query":"(CREATE|DROP|ALTER|GRANT|REVOKE|CREATE USER|DROP USER)' /var/lib/mysql/audit.log | jq -r '.timestamp, .user, .query' | paste -d' ' - - -
注意:
-
jq需提前安装;若无jq,可用python -m json.tool做基础解析 -
.user字段值为"admin@%",不含客户端 IP,无法区分同名用户不同来源(如运维跳板机 vs 应用服务器) - 高频写入场景下,
audit.log单文件可能迅速达 GB 级,需配合logrotate或插件自带轮转(企业版支持audit_log_rotate_on_size)
真正难防的不是“怎么记”,而是“谁在什么上下文里执行了什么”——audit_log 不带 session 上下文、不关联应用 traceID、不校验语句实际效果。要补全链路,必须结合工单系统、中间件日志和 binlog 解析。











