审核日志插件支持提供SQL接口来读取JSON格式的审核日志文件。(这项功能不适用于其他格式的日志文件。)
当审核日志插件初始化并配置为JSON日志记录时,它使用当前审核日志文件所在的目录作为搜索可读审核日志文件的位置。插件从audit_log_file
系统变量的值中确定文件位置、基本名称和后缀,然后查找名称与以下模式匹配的文件,其中[...]
表示可选的文件名部分:
basename[.timestamp].suffix[.gz][[.pwd_id].enc]
如果文件名以.enc
结尾,该文件是加密的,读取其未加密的内容需要从密钥环中获取解密密码。
-
如果
.enc
前面是pwd_id
,则密钥环ID为audit_log-
。pwd_id
-
如果
.enc
前面不是pwd_id
,则该文件是审核日志加密密码历史记录实现之前的旧名称。密钥环ID为audit_log
。
有关加密审核日志文件的更多信息,请参阅加密审核日志文件。
插件忽略了手动重命名的文件和不匹配模式的文件,以及使用不再可用的密码加密的文件。插件打开每个剩余的候选文件,验证文件实际包含JSON
审核事件,并使用每个文件的第一个事件的时间戳对文件进行排序。结果是一个文件序列,subject to access using the log-reading functions:
-
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()
之前返回了一个以JSON
null
值结尾的数组。 -
最新的读取序列已经通过将
JSON
null
值传递给audit_log_read()
关闭。
要在这些条件下读取事件,需要首先通过调用
audit_log_read()
并指定一个位置来初始化读取序列。 -
要指定 audit_log_read()
的位置,需要包含一个指示从何处开始读取的参数。例如,传递一个书签,即一个包含 timestamp
和 id
元素的 JSON
哈希表,该哈希表唯一标识一个特定的事件。下面是一个通过调用 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
:audit 日志中要读取的第一个事件的位置。该位置以时间戳形式给出,读取从该时间戳值或更晚的第一个事件开始。start
项的格式如下,其中value
是一个文字时间戳值:"start": { "timestamp": "value" }
-
timestamp
,id
:audit 日志中要读取的第一个事件的位置。timestamp
和id
项一起组成了一个书签,唯一标识一个特定的事件。如果audit_log_read()
参数中包含任一项,必须包含两者以完全指定一个位置,否则将发生错误。 -
max_array_length
:从日志中读取的最大事件数。如果省略该项,默认是读取到日志的末尾或读取缓冲区满,ichever comes first。
要指定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.3中也可以使用,对于这些版本来说,它基本上是一个no-op且无害。
如果从mysql客户端内部调用审核日志函数,二进制字符串结果将使用十六进制表示,取决于--binary-as-hex
选项的值。有关该选项的更多信息,请参阅第 6.5.1 节,“mysql — MySQL 命令行客户端”。
要设置audit_log_read()
读取的字节数限制,可以设置audit_log_read_buffer_size
系统变量。该变量的默认值为 32KB,可以在运行时设置。每个客户端都应该根据其使用audit_log_read()
的情况设置适当的会话值audit_log_read_buffer_size
。
每次调用audit_log_read()
都将返回尽可能多的可用事件,直到达到缓冲区大小。缓冲区大小不足的事件将被跳过并生成警告。因此,在评估应用程序的适当缓冲区大小时,需要考虑以下因素:
-
在调用
audit_log_read()
的次数和每次调用返回的事件数之间存在权衡:-
使用较小的缓冲区大小,调用将返回较少的事件,因此需要更多的调用。
-
使用较大的缓冲区大小,调用将返回更多的事件,因此需要较少的调用。
-
-
使用较小的缓冲区大小,例如默认的 32KB 大小,有更高的可能性事件将超过缓冲区大小,从而被跳过。
有关审核日志读取函数的更多信息,请参阅审核日志函数。