审计日志插件支持提供 SQL 接口来读取 JSON 格式审计日志文件的函数。(此功能不适用于以其他格式编写的日志文件。)
当审计日志插件初始化并配置为 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
值结尾的数组。最近的读取序列已通过向
audit_log_read()
传递一个JSON
null
值来关闭。
要在这些情况下读取事件,您需要首先通过使用指定位置的参数调用
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
:要读取的第一个事件在审计日志中的位置。该位置以时间戳的形式给出,读取操作将从时间戳值或之后发生的第一个事件开始。start
项的格式如下,其中value
是一个文本时间戳值:"start": { "timestamp": "value" }
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 客户端内部调用审计日志函数,则二进制字符串结果将使用十六进制表示法显示,具体取决于 --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),事件超过缓冲区大小并因此被跳过的可能性就越大。
有关审计日志读取函数的更多信息,请参阅 审计日志函数。