MySQL 5.7原生不支持init_connect实现全量SQL审计,因其仅对认证成功的普通用户生效、同步阻塞、无法捕获执行语句及结果;推荐使用server_audit插件或临时启用general_log。

MySQL 5.7 原生不支持通过 init_connect 实现真正意义上的全量 SQL 审计日志。它只能在用户成功连接后执行一段 SQL,无法捕获连接失败、权限拒绝、语法错误、SET 变量类语句,更无法记录执行结果或内部操作。强行用它“模拟审计”,漏报严重、易被绕过、还可能引发连接阻塞或死锁。
为什么 init_connect 不适合做审计日志
很多人看到 init_connect 能在每次连接时执行 SQL,就想拿它往日志表里插一条“用户上线”记录,再配合触发器或代理层补全操作——这条路走不通。
-
init_connect只对**成功通过认证的普通用户**生效,root 或带SUPER权限的用户完全绕过它 - 它执行的是**同步阻塞操作**:如果日志表写入慢、锁表、或 SQL 报错(比如字段类型不匹配),新连接会卡住甚至失败
- 它不感知后续任何 SQL 执行,
SELECT、UPDATE、DROP等操作根本不会触发它;想“补全”,必须依赖应用层改代码或中间件,失去数据库侧审计意义 - 无法区分是应用连接还是监控探针(如
SELECT 1健康检查),日志噪音极大
真正可用的替代方案:server_audit 插件(推荐)
MySQL 5.7.20+ 社区版可安全使用 MariaDB 的 server_audit 插件,它才是面向生产环境的轻量级审计选择。
- 下载匹配你 MySQL 架构(
x86_64或aarch64)和版本(如5.7.34)的server_audit.so,来源必须是 MariaDB 官网 tarball,别用第三方编译包 - 确认
plugin_dir路径:SHOW VARIABLES LIKE 'plugin_dir';,把文件放进去并chown mysql:mysql - 动态加载:
INSTALL PLUGIN server_audit SONAME 'server_audit.so';,然后立刻设关键参数:SET GLOBAL server_audit_logging = ON;SET GLOBAL server_audit_events = 'connect,query,table';SET GLOBAL server_audit_output_type = 'file';SET GLOBAL server_audit_file_path = '/var/log/mysql/audit.log'; -
query事件只记录真正访问表的语句(如SELECT * FROM users),但不记录SELECT NOW()这类无表操作;table事件覆盖CREATE/DROP/ALTER,不含GRANT
如果真要临时抓所有语句:general_log 是唯一可行的原生方式
它不是审计插件,但能最接近“全量记录客户端发来的每条原始语句”,包括连接、断开、空行、错误命令(只要进了协议层)。
- 运行时开启:
SET GLOBAL general_log = ON;(需SUPER权限) - 务必设为文件输出:
SET GLOBAL log_output = 'FILE';,避免写入mysql.general_log表引发锁竞争 - 日志路径由
general_log_file控制,默认在datadir下,建议显式指定:SET GLOBAL general_log_file = '/var/log/mysql/general.log'; - 它不记录执行结果、权限判断过程、存储过程内部语句;且日志体积爆炸快——1000 QPS 的业务,一小时就能生成数 GB 文本
- MySQL 不自动轮转,必须配
logrotate或外部脚本,否则磁盘必满
别在 init_connect 上浪费时间设计“伪审计”。要么用 server_audit 做权限与操作粒度可控的生产审计,要么用 general_log 临时抓原始流量——两者都得配合权限控制、路径写入权限、磁盘轮转,缺一不可。


















