
audit_log 插件在 MySQL 5.7 中默认不启用,且不能记录 SQL 语句体(如 SELECT * FROM users),只记录连接、断开、查询开始/结束等事件元数据;想“看到用户执行了什么 SQL”,必须搭配外部工具或换用第三方插件(如 MariaDB 的 server_audit)。
audit_log.so 能否直接记录 SELECT/INSERT 等语句内容?
不能。MySQL 官方 audit_log 插件(5.7.17+ 自带)从设计上就**不捕获 SQL 文本**。它只记录事件类型(connect、disconnect、query_start、query_end)、用户、主机、时间戳、数据库名、表名(若涉及)、影响行数等元信息。日志里不会出现 DELETE FROM orders WHERE id=123 这类原始语句。
常见误判现象:
- 配置全对、插件状态为
ACTIVE,但日志里只有connect/disconnect—— 这是正常行为,不是插件没生效 - 用
grep "SELECT"在 JSON 日志里搜不到结果 —— 因为根本没写进去 - 以为
audit_log_policy=ALL就等于“所有 SQL 都落盘” —— 实际它只扩大事件类型覆盖范围(比如增加table_access),不触发语句体记录
为什么 audit_log_format=STATEMENT 会失败?
因为该值根本不存在于 MySQL 5.7.28+ 和 8.0.x 的实现中。audit_log_format 只接受两个合法值:JSON 和 NEWLINE(OLD 已弃用)。官方文档中残留的 “STATEMENT” 是旧版 Enterprise Audit 插件的误导性描述。
实操后果:
- 设成
STATEMENT或任何非法值 →mysqld启动时报错Plugin 'audit_log' init function returned error - 配置文件中带空格或引号(如
audit_log_format = "JSON")→ 插件静默加载失败,日志为空 - 在线执行
SET GLOBAL audit_log_format = 'JSON'→ 不生效,该变量是只读的(read_only)
正确写法:在 my.cnf 的 [mysqld] 段下写一行 audit_log_format=JSON,无空格、无引号、无注释,然后重启 mysqld。
audit_log_file 写不出日志?先查这三件事
插件显示 ACTIVE,但指定路径下始终没生成文件,或文件为空,大概率是权限或路径问题。
排查顺序:
- 确认
mysqld进程运行用户(如mysql),再用sudo -u mysql touch /path/to/audit.log测试写权限;别设到/var/log/mysql/这类 root-owned 目录,推荐/var/lib/mysql/audit.log(与数据目录同级,权限通常一致) - 检查 MySQL 错误日志(
mysqld.err),搜索audit_log或Can't open,常直接报出Permission denied或No such file or directory - SELinux 或 AppArmor 启用时会拦截写操作;临时关闭测试:
setenforce 0(CentOS/RHEL)或aa-disable(Ubuntu)
注意:audit_log_file 路径受 secure_file_priv 限制,跨挂载点(如 NFS、tmpfs)可能导致 O_APPEND 失败,表现为日志写入中断。
想真正看到用户执行的 SQL,该怎么做?
MySQL 5.7 原生 audit_log 插件做不到。可行路径只有两条:
- 换用 MariaDB 的
server_audit插件(支持server_audit_events=query,可记录完整 SQL),但需确认兼容性——MySQL 5.7.34+ 已明确不支持该插件,强行加载会报错ERROR 1123 (HY000): Can't initialize function 'server_audit'; Plugin is not loaded - 改用 McAfee/Trellix 开源的
audit-plugin(如 v1.1.10),它通过符号偏移注入方式捕获 SQL 文本,但需严格匹配 MySQL 版本和构建编号(如 5.7.37 + build 980),且安装前要运行 offset 提取脚本,否则加载失败
最易被忽略的一点:即使换了第三方插件,mysqldump、mysqlpump、存储过程内动态 SQL、复制线程操作,仍可能不被记录——这些属于协议层绕过,不是配置能解决的。











