audit_log插件不记录数据篡改结果,仅记录执行成功的sql语句;需结合binlog或行级变更捕获追溯实际修改内容,其核心作用是识别“谁在何时执行了update/delete”,而非“数据被改成什么样”。

audit_log 插件本身**不记录数据篡改结果,只记录执行成功的 SQL 语句**。想靠它“排查非法篡改”,必须先明确:它能捕获的是“谁在什么时间发了哪条 UPDATE/DELETE”,而不是“某行数据实际被改成了什么”。真要追溯篡改痕迹,得结合 binlog + 时间点恢复,或启用行级变更捕获(如 MySQL 9.6.0 的 SQL 层外键与 Binlog 一致性机制)。但就审计日志本身而言,开启它并配置得当,是发现异常操作的第一道防线。
确认 audit_log 插件是否可用且已加载
插件没装、没启、没配对,日志就是空的——所有后续分析都白搭。
- 先查版本:
SELECT VERSION();。社区版必须 ≥8.0.19;企业版 ≥5.7.28才原生支持audit_log - 再查插件状态:
SHOW PLUGINS LIKE 'audit_log';。输出为空,或Status是DISABLED,说明没生效 - 如果未加载,执行:
INSTALL PLUGIN audit_log SONAME 'audit_log.so';(Linux)或'audit_log.dll'(Windows) -
注意:仅 SQL 安装是临时的,重启即丢。必须写进
my.cnf的[mysqld]段,加这三行:
plugin_load_add = audit_log.so audit_log = FORCE_PLUS_PERMANENT audit_log_format = JSON
改完必须 systemctl restart mysqld,FLUSH PRIVILEGES 或 service mysql reload 都不生效。
audit_log_policy 必须设为 COMMANDS 或 ALL,LOGINS 不够用
设成 audit_log_policy = LOGINS 只记连接/断开事件,完全看不到任何 UPDATE、DELETE、INSERT 行为——也就是根本抓不到篡改动作。
-
COMMANDS:记录所有非管理类语句(SELECT、INSERT、UPDATE、DELETE、EXECUTE),适合盯住敏感表的写操作 -
ALL:额外包含CONNECT、DISCONNECT、ACCESS(如GRANT、DROP USER),但 IO 压力大,高并发下容易打满磁盘 - 配置方式只能在
my.cnf中写:audit_log_policy = COMMANDS,然后重启;SET GLOBAL audit_log_policy = 'COMMANDS'在 8.0.23+ 支持,但不推荐依赖运行时设置
audit_log_file 和权限必须提前配好,否则日志写不进去
默认日志混在 error_log 里,根本没法筛;单独设路径又常因权限失败而静默丢弃。
- 务必在
my.cnf的[mysqld]段显式指定:audit_log_file = /var/log/mysql/audit.json - 路径必须是绝对路径,不能含变量(如
$DATADIR) -
/var/log/mysql/目录需由mysql用户拥有写权限:chown mysql:mysql /var/log/mysql - SELinux 启用时,还要检查上下文:
ls -Z /var/log/mysql,必要时执行:semanage fcontext -a -t mysqld_etc_t "/var/log/mysql(/.*)?"并restorecon -Rv /var/log/mysql - 日志不轮转,得靠
logrotate外部管理;不设audit_log_rotate_on_size就一直追加,磁盘爆满是常见故障点
从 JSON 日志里快速定位疑似篡改行为
日志是单行 JSON,人眼难读,但字段固定,适合用 jq 或简单 grep 筛选。
- 重点关注字段:
"command": "Update_rows"或"command": "Delete_rows"(MySQL 8.0.21+),或更通用的"status": 0(成功) +"query"含UPDATE/DELETE - 快速查最近 10 条更新语句:
tail -n 100 /var/log/mysql/audit.json | jq -r 'select(.command == "Update_rows" or (.query and contains("UPDATE"))) | "\(.timestamp) \(.user) \(.query)"' - 查失败的登录尝试(可能预示暴力破解):
grep '"status": 1045' /var/log/mysql/audit.json | head -10 - 若只想监控几张表,MySQL 8.0.22+ 支持:
audit_log_include_tables = 'users,orders,payments',避免全库日志噪音
真正棘手的篡改往往来自绕过 SQL 接口的操作(比如直接改系统表、用 FLUSH PRIVILEGES 提权后操作),audit_log 对这些无能为力——它只管 COM_QUERY 协议层的语句。需要这类深度审计,得上统一审计平台或结合 binlog 解析做二次校验。











