审计日志插件支持提供 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
值结尾。通过将
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" }
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),事件超出缓冲区大小的可能性更大,因此可能会被跳过。
有关审计日志读取函数的更多信息,请参见 审计日志函数。