审计日志插件支持为读取 JSON 格式的审计日志文件提供 SQL 接口的函数。(此功能不适用于以其他格式编写的日志文件。)
当审计日志插件初始化并配置为 JSON 日志记录时,它使用包含当前审计日志文件的目录作为搜索可读审计日志文件的位置。该插件根据系统变量的值确定文件位置、基本名称和后缀audit_log_file
,然后查找名称与以下模式匹配的文件,其中[...]
表示可选的文件名部分:
basename[.timestamp].suffix[.gz][[.pwd_id].enc]
如果文件名以 结尾.enc
,则文件已加密,读取未加密的内容需要从密钥环中获取解密密码。审计日志插件确定解密密码的密钥环 ID,如下所示:
如果
.enc
前面有pwd_id
,则密钥环 ID 为 。audit_log-
pwd_id
如果
.enc
前面没有pwd_id
,则该文件具有实施审核日志加密密码历史记录之前的旧名称。密钥环 ID 是audit_log
.
有关加密审计日志文件的更多信息,请参阅 加密审计日志文件。
该插件会忽略手动重命名且与模式不匹配的文件,以及密钥环中不再可用的密码加密文件。该插件打开每个剩余的候选文件,验证该文件是否实际包含JSON
审计事件,并使用每个文件的第一个事件的时间戳对文件进行排序。结果是一系列文件,这些文件可以使用日志读取功能进行访问:
audit_log_read()
从审计日志中读取事件或关闭读取进程。audit_log_read_bookmark()
返回最近写入的审核日志事件的书签。此书签适合传递给以audit_log_read()
指示从哪里开始阅读。
audit_log_read()
接受一个可选的JSON
字符串参数,成功调用任一函数返回的结果都是一个JSON
字符串。
要使用函数读取审计日志,请遵循以下原则:
调用
audit_log_read()
以读取从给定位置或当前位置开始的事件,或关闭读取:要初始化审核日志读取序列,请传递一个参数以指示开始位置。一种方法是传递由返回的书签
audit_log_read_bookmark()
:SELECT audit_log_read(audit_log_read_bookmark());
要从序列中的当前位置继续读取,请
audit_log_read()
在不指定位置的情况下调用:SELECT audit_log_read();
要显式关闭读取序列,请传递一个 参数:
JSON
null
SELECT audit_log_read('null');
没有必要明确关闭阅读。
audit_log_read()
当会话结束或通过使用指示开始位置的参数 调用来初始化新读取序列时,读取将隐式关闭 。
成功调用
audit_log_read()
读取事件会返回JSON
包含审计事件数组的字符串:如果返回的数组的最终值不是一个 值,则在刚刚读取的事件之后还有更多事件, 可以再次调用以读取更多事件。
JSON
null
audit_log_read()
如果返回数组的最终值是一个 值,则当前读取序列中没有更多的事件需要读取。
JSON
null
每个非
null
数组元素都是一个表示为JSON
散列的事件。例如:[ { "timestamp": "2020-05-18 13:39:33", "id": 0, "class": "connection", "event": "connect", ... }, { "timestamp": "2020-05-18 13:39:33", "id": 1, "class": "general", "event": "status", ... }, { "timestamp": "2020-05-18 13:39:33", "id": 2, "class": "connection", "event": "disconnect", ... }, null ]
有关 JSON 格式审计事件内容的更多信息,请参阅JSON 审计日志文件格式。
在
audit_log_read()
以下任何情况下,调用未指定位置的读取事件都会产生错误:尚未通过将位置传递给来初始化读取序列
audit_log_read()
。当前读取序列中没有更多事件需要读取;也就是说,
audit_log_read()
先前返回了一个以值结尾的数组 。JSON
null
最近的读取序列已通过将值 传递给关闭。
JSON
null
audit_log_read()
要在这些条件下读取事件,必须首先通过
audit_log_read()
使用指定位置的参数调用来初始化读取序列。
要指定 的位置
audit_log_read()
,请包含一个参数,指示从哪里开始阅读。例如,传递一个书签,它是一个JSON
散列,包含唯一标识特定事件的元素timestamp
。
id
这是一个示例书签,通过调用
audit_log_read_bookmark()
函数获得:
mysql> SELECT audit_log_read_bookmark();
+-------------------------------------------------+
| audit_log_read_bookmark() |
+-------------------------------------------------+
| { "timestamp": "2020-05-18 21:03:44", "id": 0 } |
+-------------------------------------------------+
传递当前书签以
audit_log_read()
初始化从书签位置开始的事件阅读:
mysql> SELECT audit_log_read(audit_log_read_bookmark());
+-----------------------------------------------------------------------+
| audit_log_read(audit_log_read_bookmark()) |
+-----------------------------------------------------------------------+
| [ {"timestamp":"2020-05-18 22:41:24","id":0,"class":"connection", ... |
+-----------------------------------------------------------------------+
的参数audit_log_read()
是可选的。如果存在,它可以是
关闭读取序列的值或
散列。
JSON
null
JSON
在 的散列参数中
audit_log_read()
,项是可选的,并且控制读取操作的各个方面,例如开始读取的位置或要读取的事件数。以下项目很重要(其他项目被忽略):
start
:要读取的第一个事件在审核日志中的位置。该位置作为时间戳给出,读取从时间戳值或之后发生的第一个事件开始。该start
项目具有这种格式,其中value
是文字时间戳值:"start": { "timestamp": "value" }
start
从MySQL 8.0.22 开始允许 该项目。timestamp
,id
: 要读取的第一个事件在审核日志中的位置。timestamp
和id
项目一起构成了唯一标识特定事件的书签。如果audit_log_read()
参数包含其中一项,则它必须包含两者才能完全指定位置,否则会发生错误。max_array_length
:从日志中读取的最大事件数。如果省略此项,则默认读取到日志末尾或直到读取缓冲区已满,以先到者为准。
要为 指定起始位置
audit_log_read()
,请传递一个包含项目或由和
项目start
组成的书签的散列参数。如果散列参数同时包含
项目和书签,则会发生错误。
timestamp
id
start
如果散列参数未指定起始位置,则从当前位置继续读取。
如果时间戳值不包含时间部分,
00:00:00
则假定时间部分为 。
接受的示例参数
audit_log_read()
:
从给定时间戳或之后发生的第一个事件开始读取事件:
audit_log_read('{ "start": { "timestamp": "2020-05-24 12:30:00" } }')
与前面的示例一样,但最多读取 3 个事件:
audit_log_read('{ "start": { "timestamp": "2020-05-24 12:30:00" }, "max_array_length": 3 }')
从发生在当天或之后的第一个事件开始读取事件
2020-05-24 00:00:00
(时间戳不包括时间部分,因此00:00:00
是假定的):audit_log_read('{ "start": { "timestamp": "2020-05-24" } }')
从具有确切时间戳和事件 ID 的事件开始读取事件:
audit_log_read('{ "timestamp": "2020-05-24 12:30:00", "id": 0 }')
与前面的示例一样,但最多读取 3 个事件:
audit_log_read('{ "timestamp": "2020-05-24 12:30:00", "id": 0, "max_array_length": 3 }')
从读取序列中的当前位置读取事件:
audit_log_read()
从读取序列中的当前位置开始最多读取 5 个事件:
audit_log_read('{ "max_array_length": 5 }')
关闭当前读取序列:
audit_log_read('null')
JSON
可以根据需要操作从任一日志读取函数返回
的字符串。假设获取书签的调用产生此值:
mysql> SET @mark := audit_log_read_bookmark();
mysql> SELECT @mark;
+-------------------------------------------------+
| @mark |
+-------------------------------------------------+
| { "timestamp": "2020-05-18 16:10:28", "id": 2 } |
+-------------------------------------------------+
使用该参数调用audit_log_read()
可以返回多个事件。要限制
audit_log_read()
在大多数事件中读取,请将具有该值N
的项目添加到字符串
中。max_array_length
例如,要读取单个事件,修改字符串如下:
mysql> SET @mark := JSON_SET(@mark, '$.max_array_length', 1);
mysql> SELECT @mark;
+----------------------------------------------------------------------+
| @mark |
+----------------------------------------------------------------------+
| {"id": 2, "timestamp": "2020-05-18 16:10:28", "max_array_length": 1} |
+----------------------------------------------------------------------+
修改后的字符串在传递给 时
audit_log_read()
,会生成一个最多包含一个事件的结果,无论有多少事件可用。
在 MySQL 8.0.19 之前,审计日志函数的字符串返回值是二进制字符串。要将二进制字符串与需要非二进制字符串的函数(例如处理JSON
值的函数)一起使用,请将其转换为非二进制字符串。例如,在将书签传递给 之前JSON_SET()
,将其转换utf8mb4
为如下所示:
SET @mark = CONVERT(@mark USING utf8mb4);
该语句甚至可以用于 MySQL 8.0.19 及更高版本;对于那些版本,它本质上是空操作并且是无害的。
如果从mysql客户端
中调用审计日志功能
,二进制字符串结果将使用十六进制表示法显示,具体取决于
--binary-as-hex
. 有关该选项的更多信息,请参阅第 4.5.1 节,“mysql — MySQL 命令行客户端”。
要限制
audit_log_read()
读取的字节数,请设置
audit_log_read_buffer_size
系统变量。从 MySQL 8.0.12 开始,这个变量默认为 32KB,可以在运行时设置。每个客户端都应将其会话值设置为
audit_log_read_buffer_size
适合其对
audit_log_read()
.
每次调用audit_log_read()
都会返回适合缓冲区大小的尽可能多的可用事件。不适合缓冲区大小的事件将被跳过并生成警告。鉴于此行为,在评估应用程序的适当缓冲区大小时应考虑以下因素:
audit_log_read()
调用次数和每次调用返回的事件 之间存在权衡 :使用较小的缓冲区大小,调用返回较少的事件,因此需要更多的调用。
缓冲区大小越大,调用返回的事件越多,因此需要的调用越少。
使用较小的缓冲区大小(例如默认大小 32KB),事件更有可能超过缓冲区大小并因此被跳过。
在 MySQL 8.0.12 之前,
audit_log_read_buffer_size
默认值为 1MB,影响所有客户端,并且只能在服务器启动时更改。
有关审核日志读取功能的其他信息,请参阅审核日志功能。