MySQL社区版默认不记录SQL,需用general_log临时排查或安装server_audit插件实现审计;企业版才原生支持audit_log插件。

MySQL 默认不记录执行过的 SQL,必须手动开启审计日志插件
MySQL 社区版默认完全不保存历史 SQL 记录,general_log 是最接近的替代方案,但它不是审计日志,也不带用户、时间、返回状态等关键字段。真正的审计能力依赖 audit_log 插件,而该插件仅在 MySQL 企业版中官方支持;社区版需借助第三方插件(如 MariaDB 的 server_audit)或用 general_log + 日志解析临时顶替。
用 general_log 快速查看最近执行的 SQL(适合开发/排障)
这是社区版唯一开箱即用的“记录执行 SQL”方式,但性能开销大,不能长期开启。
-
SET GLOBAL general_log = ON;—— 动态开启,立即生效 -
SET GLOBAL general_log_file = '/var/log/mysql/general.log';—— 指定路径,需 MySQL 进程有写权限 - 日志格式是纯文本,每行含时间、连接 ID、命令类型(
Query/Connect/Quit)、SQL 内容 - 注意:
general_log不记录参数化查询的真实值(如PREPARE+EXECUTE中的?值不会展开) - 高并发下 I/O 压力明显,线上环境开启超过几分钟就可能拖慢 QPS
社区版想做审计级记录?绕不开 server_audit 插件(MariaDB 兼容)
MySQL 社区版原生不提供审计插件,但很多生产环境会混用 MariaDB 的 server_audit(它支持 MySQL 5.7+,需手动安装 SO 文件)。
- 下载对应版本的
server_audit.so(注意架构和 MySQL 版本匹配,否则INSTALL PLUGIN报错Can't open shared library) -
INSTALL PLUGIN server_audit SONAME 'server_audit.so';—— 安装后需重启或至少刷新权限 - 关键配置项:
SET GLOBAL server_audit_logging=ON;、SET GLOBAL server_audit_events='CONNECT,QUERY,TABLE'; - 输出到文件时,默认不含 SQL 参数值(如
WHERE id = ?仍显示为?),也无法区分存储过程内部语句 - 日志是追加写,不自动轮转,得靠外部工具(如
logrotate)切分,否则单文件可能涨到几十 GB
为什么不用 binlog 查“执行过的 SQL”?
binlog 记的是数据变更的逻辑日志(INSERT/UPDATE/DELETE),且默认是 ROW 格式——你看到的是“哪几行变了”,不是原始 SQL;即使设成 STATEMENT,也只记录主库执行的语句,不包括 SELECT、SHOW、SET 等非更新语句,更不记录失败语句。
-
mysqlbinlog --base64-output=DECODE-ROWS -v只能还原 ROW 模式下的变更细节,无法反推原始 SQL -
binlog_format = STATEMENT在 GTID 或某些函数(如NOW())下不安全,MySQL 8.0+ 已限制其使用场景 - 它本质是复制日志,不是审计日志;开启
binlog不等于开启 SQL 记录功能
真正要审计,得明确需求边界:是查某次故障时谁执行了什么,还是持续监控高危操作?前者用 general_log 临时抓一下就行;后者必须接受插件依赖和维护成本——没有免配置、零性能损耗、全兼容的方案。


















