技术社群的这篇文章《MySQL 8.0 社区版如何使用 Percona 审计插件?》给我们讲解了MySQL 8.0的社区版增加Percona审计插件的操作,如果有审计相关的需求,可以了解下。
随着 MySQL 5.7 版本 EOL,许多客户都逐渐升级到 MySQL 8.0 版本,早期用社区版 5.7 版本时,MariaDB[1] 审计插件通过调整源码适配,基本可兼容覆盖 5.7 绝大部门主流版本。8.0 后,MariaDB 插件不再兼容(或者说 MySQL 8.0 不再兼容 MariaDB),需要寻求一个社区版可用的审计插件。
早期 Percona[2] 官方明确表示,审计插件为 Percona Server 设计,未考虑 Oracle MySQL,也未做兼容适配,但在 2024 年 7 月,Percona 社区发文[3] 验证审计插件支持 MySQL 8.0 版本,并做了示例演示。
本文基于该背景,本地做基础验证,评估 Percona 审计插件和 MySQL 8.0 兼容性情况以及是否存在异常问题。
从 Percona 安装软件包中提取出审计插件 audit_log.so 备用。
shell> mkdir -p Percona-Server-8.0.37-29-Linux.x86_64.glibc2.17/lib/plugin/
shell> tar -xvf Percona-Server-8.0.37-29-Linux.x86_64.glibc2.17.tar.gz --wildcards --no-anchored '*audit_log.so*'
shell> ls -al Percona-Server-8.0.37-29-Linux.x86_64.glibc2.17/lib/plugin/audit_log.so
-rwxr-xr-x 1 root root 914544 Aug 18 2024 Percona-Server-8.0.37-29-Linux.x86_64.glibc2.17/lib/plugin/audit_log.so
将提前出的 audit_log.so 审计插件,放置在 MySQL 插件对应目录即可。
shell> mysql -u root -p --socket=/data/mysql/mysqldata3306/sock/mysql.sock
确认 MySQL 插件目录
mysql> show global variables like 'plugin_dir';
+---------------+------------------------------+
| Variable_name | Value |
+---------------+------------------------------+
| plugin_dir | /usr/local/mysql/lib/plugin/ |
+---------------+------------------------------+
1 row in set (0.03 sec)
将审计插件拷贝至 MySQL 插件目录并调整好权限
shell> cp /usr/local/Percona-Server-8.0.37-29-Linux.x86_64.glibc2.17/lib/plugin/audit_log.so /usr/local/mysql/lib/plugin/
shell> chown mysql:mysql /usr/local/mysql/lib/plugin/audit_log.so
登录数据库安装审计插件。
shell> mysql -u root -p --socket=/data/mysql/mysqldata3306/sock/mysql.sock
mysql> install plugin audit_log soname 'audit_log.so';
Query OK, 0 rows affected (0.02 sec)
验证安装成功
mysql> select * from mysql.plugin;
+-----------+--------------+
| name | dl |
+-----------+--------------+
| audit_log | audit_log.so |
+-----------+--------------+
1 row in set (0.01 sec)
mysql> SELECT PLUGIN_NAME, PLUGIN_STATUS, PLUGIN_TYPE
-> FROM INFORMATION_SCHEMA.PLUGINS
-> WHERE PLUGIN_NAME = 'audit_log';
+-------------+---------------+-------------+
| PLUGIN_NAME | PLUGIN_STATUS | PLUGIN_TYPE |
+-------------+---------------+-------------+
| audit_log | ACTIVE | AUDIT |
+-------------+---------------+-------------+
插件安装完成后会新增 10 余个相关参数。
mysql> show global variables like 'audit%';
+-----------------------------+-----------------------------------------+
| Variable_name | Value |
+-----------------------------+-----------------------------------------+
| audit_log_buffer_size | 1048576 | #审计日志的缓冲区大小,单位为字节
| audit_log_exclude_accounts | orchestrator'@'10* | #指定不记录审计日志的数据库账号
| audit_log_exclude_commands | | #指定不记录审计日志的命令类型
| audit_log_exclude_databases | | #指定不记录审计日志的数据库
| audit_log_file | /data/mysql/mysqldata3306/log/audit.log | #审计日志文件的存储路径和文件名
| audit_log_flush | OFF | #控制是否自动刷新审计日志缓冲区到磁盘(OFF 表示关闭自动刷新)
| audit_log_format | JSON | #审计日志的文件格式
| audit_log_handler | FILE | #审计日志的输出方式
| audit_log_include_accounts | | #指定仅记录这些账号的审计日志
| audit_log_include_commands | | #指定仅记录这些命令类型的审计日志
| audit_log_include_databases | | #指定仅记录这些数据库的审计日志
| audit_log_policy | LOGINS | #审计日志的核心记录策略(LOGINS 表示仅记录登录相关事件)
| audit_log_rotate_on_size | 1073741824 | #日志文件自动轮转的触发阈值(单位:字节)
| audit_log_rotations | 7 | #日志轮转后保留的历史日志文件数量(最多保留 7 个)
| audit_log_strategy | ASYNCHRONOUS | #审计日志的写入策略(ASYNCHRONOUS 表示异步写入)
| audit_log_syslog_facility | LOG_USER | #指定审计日志发送到系统日志时的 “设备类型”(facility),用于分类系统日志的来源
| audit_log_syslog_ident | percona-audit | #指定审计日志在系统日志中的 “标识字符串”(identifier),用于区分不同应用的日志。
| audit_log_syslog_priority | LOG_INFO | #指定审计日志在系统日志中的 “优先级”(priority),用于标记日志的重要程度
+-----------------------------+-----------------------------------------+
18 rows in set (0.02 sec)
基于默认规则,可以看到审计插件已启用并记录审计日志。

审计日志
审计日志片段字段含义。
{
"audit_record": {
"name": "Connect", //表示审计记录的事件类型
"record": "2_2025-09-05T07:01:54", //计记录的唯一标识(ID)
"timestamp": "2025-09-05T07:04:44Z", //登录事件发生的时间戳(UTC 时间)
"connection_id": "8", //本次数据库连接的唯一会话 ID
"status": 0, //登录操作的状态码
"user": "root", //客户端登录时使用的用户名
"priv_user": "root", //实际授予权限的用户
"os_login": "", //客户端操作系统的用户名
"proxy_user": "", //代理用户(若通过代理登录)
"host": "localhost", //客户端连接的主机名
"ip": "", //客户端的 IP 地址
"db": "" //登录时指定的默认数据库
}
}
audit_log_policy 参数可以动态修改,满足 ALL、LOGINS、QUERIES 和 NONE 四种类型
audit.log 按照参数的设置输出相应的日志类型,这里测试 QUERIES 的。
root@localhost:(none) 8.0.37 05:22:16> SET GLOBAL audit_log_policy = 'QUERIES';
Query OK, 0 rows affected (0.00 sec)
root@localhost:(none) 8.0.37 05:23:31> select * from sys.sys_config;
+--------------------------------------+-------+---------------------+--------+
| variable | value | set_time | set_by |
+--------------------------------------+-------+---------------------+--------+
| diagnostics.allow_i_s_tables | OFF | 2025-09-05 06:29:55 | NULL |
| diagnostics.include_raw | OFF | 2025-09-05 06:29:55 | NULL |
| ps_thread_trx_info.max_length | 65535 | 2025-09-05 06:29:55 | NULL |
| statement_performance_analyzer.limit | 100 | 2025-09-05 06:29:55 | NULL |
| statement_performance_analyzer.view | NULL | 2025-09-05 06:29:55 | NULL |
| statement_truncate_len | 64 | 2025-09-05 06:29:55 | NULL |
+--------------------------------------+-------+---------------------+--------+
6 rows in set (0.00 sec)

audit_log_format 支持 OLD、NEW、CSV、JSON 四种形式;
这里展现 JSON 形式。

测试添加排除的用户 test,测试生效,日志不会记录该用户的操作。
test@127.0.0.1:(none) 8.0.37 05:25:35> select * from sys.sys_config;
+--------------------------------------+-------+---------------------+--------+
| variable | value | set_time | set_by |
+--------------------------------------+-------+---------------------+--------+
| diagnostics.allow_i_s_tables | OFF | 2025-09-05 06:29:55 | NULL |
| diagnostics.include_raw | OFF | 2025-09-05 06:29:55 | NULL |
| ps_thread_trx_info.max_length | 65535 | 2025-09-05 06:29:55 | NULL |
| statement_performance_analyzer.limit | 100 | 2025-09-05 06:29:55 | NULL |
| statement_performance_analyzer.view | NULL | 2025-09-05 06:29:55 | NULL |
| statement_truncate_len | 64 | 2025-09-05 06:29:55 | NULL |
+--------------------------------------+-------+---------------------+--------+
6 rows in set (0.00 sec)
test@127.0.0.1:(none) 8.0.37::> SET GLOBAL audit_log_exclude_accounts = "'orchestrator'@'10%','test'@'%'";
Query OK, 0 rows affected (0.00 sec)
test@127.0.0.1:(none) 8.0.37 05:29:53> select * from sys.sys_config;
+--------------------------------------+-------+---------------------+--------+
| variable | value | set_time | set_by |
+--------------------------------------+-------+---------------------+--------+
| diagnostics.allow_i_s_tables | OFF | 2025-09-05 06:29:55 | NULL |
| diagnostics.include_raw | OFF | 2025-09-05 06:29:55 | NULL |
| ps_thread_trx_info.max_length | 65535 | 2025-09-05 06:29:55 | NULL |
| statement_performance_analyzer.limit | 100 | 2025-09-05 06:29:55 | NULL |
| statement_performance_analyzer.view | NULL | 2025-09-05 06:29:55 | NULL |
| statement_truncate_len | 64 | 2025-09-05 06:29:55 | NULL |
+--------------------------------------+-------+---------------------+--------+
6 rows in set (0.00 sec)
发现排除 test 用户后无日志输出。

audit_log_include_commands:指定需要被记录到审计日志中的特定数据库命令类型。
可以通过该语句查询出插件支持所有语句类型。
mysql> SELECT name FROM performance_schema.setup_instruments WHERE name LIKE "statement/sql/%" ORDER BY name;
+-----------------------------------------------+
| name |
+-----------------------------------------------+
| statement/sql/alter_db |
| statement/sql/alter_event |
| statement/sql/alter_function |
| statement/sql/alter_instance |
| statement/sql/alter_procedure |
| statement/sql/alter_resource_group |
......
......
| statement/sql/update_multi |
| statement/sql/xa_commit |
| statement/sql/xa_end |
| statement/sql/xa_prepare |
| statement/sql/xa_recover |
| statement/sql/xa_rollback |
| statement/sql/xa_start |
+-----------------------------------------------+
159 rows in set (0.01 sec)
支持 159 种!
这里测试设置 begin,是否只会记录 begin 语句。
测试前要先将 audit_log_policy 调整成 ALL 或者 QUERIES,不然日志不会有记录。
mysql> SET GLOBAL audit_log_policy = 'ALL';
Query OK, 0 rows affected (0.01 sec)
mysql> SET GLOBAL audit_log_include_commands = 'begin';
Query OK, 0 rows affected (0.01 sec)
mysql> begin;
Query OK, 0 rows affected (0.00 sec)

如果设置为NULL,则不会记录任何语句。


作用:用于指定不需要被审计记录的数据库名称,实现 “排除特定数据库的所有操作” 的审计过滤效果。
添加 audit_log_exclude_databases = 'mysql','test_%',重启登录数据库。
mysql> SELECT @@global.audit_log_exclude_databases;
+--------------------------------------+
| @@global.audit_log_exclude_databases |
+--------------------------------------+
| mysql','test_% |
+--------------------------------------+
1 row in set (0.00 sec)
mysql> select * from test_ddl_db.i1;
Empty set (0.02 sec)
root@localhost:(none) 8.0.37::> select * from sys.sys_config;
+--------------------------------------+-------+---------------------+--------+
| variable | value | set_time | set_by |
+--------------------------------------+-------+---------------------+--------+
| diagnostics.allow_i_s_tables | OFF | 2025-09-05 06:29:55 | NULL |
| diagnostics.include_raw | OFF | 2025-09-05 06:29:55 | NULL |
| ps_thread_trx_info.max_length | 65535 | 2025-09-05 06:29:55 | NULL |
| statement_performance_analyzer.limit | 100 | 2025-09-05 06:29:55 | NULL |
| statement_performance_analyzer.view | NULL | 2025-09-05 06:29:55 | NULL |
| statement_truncate_len | 64 | 2025-09-05 06:29:55 | NULL |
+--------------------------------------+-------+---------------------+--------+
6 rows in set (0.01 sec)
查看日志发现含 test_ddl_db 库下并没有输出,sys 库下的有输出。

在 MySQL 8.0.37 版本下,Percona 审计日志记录插件可以正常被使用,并简单说明了关键的几个参数。
参考资料
[1]
MariaDB: https://mariadb.org/
[2]
Percona: https://www.percona.com/
[3]
Percona Blog: https://www.percona.com/blog/using-the-percona-audit-logging-plugin-on-mysql-community-8-0-x/