文档首页
MySQL 9.0 参考手册
相关文档 下载本手册
PDF (US Ltr) - 40.0Mb
PDF (A4) - 40.1Mb
手册页 (TGZ) - 258.2Kb
手册页 (Zip) - 365.3Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 9.0 参考手册  /  ...  /  配置审核日志特性

8.4.5.5 配置审核日志特性

本节介绍如何配置审核日志特性,例如审核日志插件写入事件的文件、写入事件的格式、是否启用日志文件压缩和加密以及空间管理。

有关影响审核日志的函数和系统变量的更多信息,请参阅 审核日志函数审核日志选项和变量

审核日志插件还可以根据事件内容或事件来源的帐户来控制哪些审核事件被写入审核日志文件。请参阅 第 8.4.5.7 节,“审核日志过滤”

审核日志文件命名约定

要配置审核日志文件名,请在服务器启动时设置 audit_log_file 系统变量。默认名称为服务器数据目录中的 audit.log。出于最佳安全考虑,将审核日志写入仅对 MySQL 服务器和具有查看日志合法理由的用户可访问的目录。

插件将 audit_log_file 值解释为由可选的前导目录名、基本名称和可选后缀组成。如果启用了压缩或加密,则有效文件名(用于创建日志文件的实际名称)将与配置的文件名不同,因为它具有额外的后缀

  • 如果启用了压缩,插件会添加 .gz 后缀。

  • 如果启用了加密,插件会添加 .pwd_id.enc 后缀,其中 pwd_id 指示要用于日志文件操作的哪个加密密码。审核日志插件将加密密码存储在密钥环中;请参阅 加密审核日志文件

有效审核日志文件名是通过将适用的压缩和加密后缀添加到配置的文件名后产生的名称。例如,如果配置的 audit_log_file 值为 audit.log,则有效文件名是下表中显示的值之一。

启用的功能 有效文件名
无压缩或加密 audit.log
压缩 audit.log.gz
加密 audit.log.pwd_id.enc
压缩、加密 audit.log.gz.pwd_id.enc

pwd_id 指示用于加密或解密文件的密码的 ID。 pwd_id 格式为 pwd_timestamp-seq,其中

  • pwd_timestampYYYYMMDDThhmmss 格式的 UTC 值,指示密码创建的时间。

  • seq 是一个序列号。序列号从 1 开始,对于具有相同 pwd_timestamp 值的密码,序列号会递增。

以下是一些 pwd_id 密码 ID 值示例

20190403T142359-1
20190403T142400-1
20190403T142400-2

为了构建用于在密钥环中存储密码的相应密钥环 ID,审计日志插件在 pwd_id 值前添加 audit_log- 前缀。对于刚刚展示的示例密码 ID,相应的密钥环 ID 为:

audit_log-20190403T142359-1
audit_log-20190403T142400-1
audit_log-20190403T142400-2

审计日志插件当前用于加密的密码的 ID 是 pwd_timestamp 值最大的那个。如果多个密码具有相同的 pwd_timestamp 值,则当前密码 ID 是序列号最大的那个。例如,在前面的密码 ID 集合中,有两个密码具有最大的时间戳,20190403T142400,因此当前密码 ID 是序列号最大的那个 (2)。

审计日志插件根据有效的审计日志文件名在初始化和终止期间执行某些操作。

  • 在初始化期间,插件检查是否存在具有审计日志文件名的文件,如果存在则将其重命名。(在这种情况下,插件假设之前的服务器调用意外退出,但审计日志插件仍在运行。)然后,插件写入一个新的空审计日志文件。

  • 在终止期间,插件会重命名审计日志文件。

  • 文件重命名(无论是在插件初始化期间还是终止期间)都按照基于大小的自动日志文件轮转的常规规则进行;请参见 手动审计日志文件轮转

选择审计日志文件格式

要配置审计日志文件格式,请在服务器启动时设置 audit_log_format 系统变量。可以使用以下格式:

  • NEW:新式 XML 格式。这是默认格式。

  • OLD:旧式 XML 格式。

  • JSON:JSON 格式。将审计日志写入 JSON 数组。只有此格式支持可选的查询时间和大小统计信息。

有关每种格式的详细信息,请参见 第 8.4.5.4 节“审计日志文件格式”

启用审计日志刷新任务

MySQL 企业审计提供设置刷新间隔以自动处理内存中缓存的功能。使用 audit_log_flush_interval_seconds 系统变量配置的刷新任务默认值为零,这意味着该任务未计划运行。

当该任务配置为运行(值为非零)时,MySQL 企业审计会在其初始化时尝试调用 调度程序 组件,并配置其内存缓存的定期、重复刷新。

  • 如果审计日志找不到调度程序注册服务的实现,它不会安排刷新并继续加载。

  • 审计日志实现 dynamic_loader_services_loaded_notification 服务,并监听 mysql_scheduler 的新注册,以便审计日志可以将其计划的任务注册到新加载的调度程序中。

  • 审计日志只将自身注册到第一个加载的调度程序实现中。

类似地,MySQL 企业审计在其反初始化时调用 scheduler 组件,并取消配置其已安排的重复刷新。它会保留对调度程序注册服务的活动引用,直到计划的任务被取消注册,确保 scheduler 组件不能在有活动计划作业时被卸载。执行调度程序及其任务的所有结果都写入服务器错误日志。

要安排审计日志刷新任务

  1. 确认 scheduler 组件已加载并启用。该组件默认情况下处于启用状态 (ON)(请参见 component_scheduler.enabled)。

    SELECT * FROM mysql.components;
    +--------------+--------------------+----------------------------+
    | component_id | component_group_id | component_urn              |
    +--------------+--------------------+----------------------------+
    |            1 |                  1 | file://component_scheduler |
    +--------------+--------------------+----------------------------+
  2. 安装 audit_log 插件(如果尚未安装)(请参见 第 8.4.5.2 节“安装或卸载 MySQL 企业审计”)。

  3. 使用 audit_log_flush_interval_seconds 启动服务器,并将该值设置为大于 59 的数字。该值的上限因平台而异。例如,要将刷新任务配置为每两分钟重复一次

    $> mysqld --audit_log_flush_interval_seconds=120

    有关更多信息,请参见 audit_log_flush_interval_seconds 系统变量。

添加查询统计信息以进行异常值检测

在 MySQL 9.0 中,您可以使用可选数据字段扩展 JSON 格式的日志文件,以显示查询时间、发送和接收的字节数、返回给客户端的行数以及检查的行数。此数据在慢查询日志中对符合条件的查询可用,在审计日志的上下文中,它也有助于检测活动分析的异常值。扩展数据字段只能在审计日志处于 JSON 格式时添加 (audit_log_format=JSON),这不是默认设置。

查询统计信息通过您作为审计日志过滤函数设置的组件服务传递到审计日志中。这些服务分别名为 mysql_audit_print_service_longlong_data_sourcemysql_audit_print_service_double_data_source。您可以为每个输出项选择任一数据类型。对于查询时间,longlong 以微秒为单位输出值,double 以秒为单位输出值。

您可以使用 audit_log_filter_set_filter() 审计日志函数添加查询统计信息,作为 JSON 过滤语法的 service 元素,如下所示:

SELECT audit_log_filter_set_filter('QueryStatistics',  
                                   '{ "filter": { "class": { "name": "general", "event": { "name": "status", "print" : '
                                   '{ "service": { "implementation": "mysql_server", "tag": "query_statistics", "element": [ '
                                   '{ "name": "query_time",     "type": "double" }, '
                                   '{ "name": "bytes_sent",     "type": "longlong" }, '
                                   '{ "name": "bytes_received", "type": "longlong" }, '
                                   '{ "name": "rows_sent",      "type": "longlong" }, '
                                   '{ "name": "rows_examined",  "type": "longlong" } ] } } } } } }');

要填充 bytes_sentbytes_received 字段,系统变量 log_slow_extra 必须设置为 ON。如果系统变量的值为 OFF,则为这些字段写入空值到日志文件。

如果要停止收集查询统计信息,请使用 audit_log_filter_set_filter() 审计日志函数删除过滤器,例如

SELECT audit_log_filter_remove_filter('QueryStatistics');
压缩审计日志文件

可以为任何日志记录格式启用审计日志文件压缩。

要配置审计日志文件压缩,请在服务器启动时设置 audit_log_compression 系统变量。允许的值为 NONE(不压缩;默认值)和 GZIP(GNU Zip 压缩)。

如果同时启用了压缩和加密,则压缩在加密之前发生。要手动恢复原始文件,请先解密,然后解压缩。请参见 手动解压缩和解密审计日志文件

加密审计日志文件

可以为任何日志记录格式启用审计日志文件加密。加密基于用户定义的密码(初始密码除外,该密码由审计日志插件生成)。要使用此功能,必须启用 MySQL 密钥环,因为审计日志使用它来存储密码。可以使用任何密钥环组件或插件;有关说明,请参见 第 8.4.4 节“MySQL 密钥环”

要配置审计日志文件加密,请在服务器启动时设置 audit_log_encryption 系统变量。允许的值为 NONE(不加密;默认值)和 AES(AES-256-CBC 密码加密)。

要在运行时设置或获取加密密码,请使用以下审计日志函数

  • 要设置当前加密密码,请调用 audit_log_encryption_password_set()。此函数将新密码存储在密钥环中。如果启用了加密,它还会执行日志文件轮转操作,该操作会重命名当前日志文件,并以密码加密的新日志文件开始。文件重命名按照基于大小的自动日志文件轮转的常规规则进行;请参见 手动审计日志文件轮转

    如果 audit_log_password_history_keep_days 系统变量不为零,则调用 audit_log_encryption_password_set() 还会导致旧的存档审计日志加密密码过期。有关审计日志密码历史记录的信息,包括密码存档和过期,请参见该变量的描述。

  • 要获取当前加密密码,请调用 audit_log_encryption_password_get(),不带参数。要按 ID 获取密码,请传递一个参数,该参数指定当前密码或已存档密码的密钥环 ID。

    要确定哪些审计日志密钥环 ID 存在,请查询 Performance Schema keyring_keys

    mysql> SELECT KEY_ID FROM performance_schema.keyring_keys
           WHERE KEY_ID LIKE 'audit_log%'
           ORDER BY KEY_ID;
    +-----------------------------+
    | KEY_ID                      |
    +-----------------------------+
    | audit_log-20190415T152248-1 |
    | audit_log-20190415T153507-1 |
    | audit_log-20190416T125122-1 |
    | audit_log-20190416T141608-1 |
    +-----------------------------+

有关审计日志加密函数的更多信息,请参见 审计日志函数

当审计日志插件初始化时,如果它发现日志文件加密已启用,则它会检查密钥环是否包含审计日志加密密码。如果没有,插件会自动生成一个随机的初始加密密码并将其存储在密钥环中。要发现此密码,请调用 audit_log_encryption_password_get()

如果同时启用了压缩和加密,则压缩在加密之前发生。要手动恢复原始文件,请先解密,然后解压缩。请参见 手动解压缩和解密审计日志文件

手动解压缩和解密审计日志文件

可以使用标准工具解压缩和解密审计日志文件。这应该只对已关闭(存档)且不再使用的日志文件进行,而不是对审计日志插件当前正在写入的日志文件进行。您可以识别存档日志文件,因为它们已被审计日志插件重命名,在基本名称之后的文件名中包含时间戳。

在本讨论中,假设 audit_log_file 设置为 audit.log。在这种情况下,存档审计日志文件具有以下表格中显示的名称之一。

启用的功能 存档文件名
无压缩或加密 audit.timestamp.log
压缩 audit.timestamp.log.gz
加密 audit.timestamp.log.pwd_id.enc
压缩、加密 audit.timestamp.log.gz.pwd_id.enc

审计日志文件的命名约定 中所述,pwd_id 格式为 pwd_timestamp-seq。因此,存档的加密日志文件的文件名实际上包含两个时间戳。第一个表示文件轮转时间,第二个表示加密密码何时创建。

考虑以下一组存档的加密日志文件名

audit.20190410T205827.log.20190403T185337-1.enc
audit.20190410T210243.log.20190403T185337-1.enc
audit.20190415T145309.log.20190414T223342-1.enc
audit.20190415T151322.log.20190414T223342-2.enc

每个文件名都有一个唯一的文件轮转时间戳。相比之下,密码时间戳不唯一

  • 前两个文件具有相同的密码 ID 和序列号 (20190403T185337-1)。它们具有相同的加密密码。

  • 后两个文件具有相同的密码 ID (20190414T223342),但序列号不同 (12)。这些文件具有不同的加密密码。

要手动解压缩压缩的日志文件,请使用 gunzipgzip -d 或等效命令。例如

gunzip -c audit.timestamp.log.gz > audit.timestamp.log

要手动解密加密的日志文件,请使用 openssl 命令。例如

openssl enc -d -aes-256-cbc -pass pass:password -md sha256
    -in audit.timestamp.log.pwd_id.enc
    -out audit.timestamp.log

要执行该命令,您必须获取 password,即加密密码。为此,请使用 audit_log_encryption_password_get()。例如,如果审计日志文件名是 audit.20190415T151322.log.20190414T223342-2.enc,则密码 ID 为 20190414T223342-2,密钥环 ID 为 audit-log-20190414T223342-2。像这样检索密钥环密码

SELECT audit_log_encryption_password_get('audit-log-20190414T223342-2');

如果对审计日志同时启用压缩和加密,则压缩在加密之前进行。在这种情况下,文件名将添加 .gz.pwd_id.enc 后缀,对应于这些操作发生的顺序。要手动恢复原始文件,请反向执行操作。也就是说,首先解密文件,然后解压缩它

openssl enc -d -aes-256-cbc -pass pass:password -md sha256
    -in audit.timestamp.log.gz.pwd_id.enc
    -out audit.timestamp.log.gz
gunzip -c audit.timestamp.log.gz > audit.timestamp.log
审计日志文件空间管理

审计日志文件可能会变得非常大,占用大量磁盘空间。如果您正在收集可选的查询时间和大小统计信息,这会增加空间需求。查询统计信息仅在 JSON 格式下受支持。

要管理使用的空间,请采用以下方法

  • 日志文件轮换。这涉及到通过重命名当前日志文件来轮换它,然后使用原始名称打开一个新的当前日志文件。轮换可以手动执行,也可以配置为自动执行。

  • 如果启用自动轮换,则修剪已轮换的 JSON 格式日志文件。修剪可以根据日志文件年龄或组合日志文件大小进行。

要配置审计日志文件空间管理,请使用以下系统变量

注意

对于 JSON 格式的日志文件,当 audit_log_format_unix_timestamp 系统变量的值在运行时发生更改时,也会发生轮换。但是,这不是出于空间管理目的,而是为了让给定的 JSON 格式日志文件中的所有记录都包含或都不包含 time 字段。

注意

已轮换(重命名)的日志文件不会自动删除。例如,使用基于大小的日志文件轮换,重命名的日志文件具有唯一的名称并且无限期地累积。它们不会从名称序列的末尾轮换。为避免过度使用空间

  • 对于 JSON 格式的日志文件:按照 审计日志文件修剪 中的说明启用日志文件修剪。

  • 否则:定期删除旧文件,并在必要时先备份它们。如果备份的日志文件已加密,请将相应的加密密码备份到安全位置,以便您在以后需要解密文件时可以使用它们。

以下部分将更详细地描述日志文件轮换和修剪。

手动审计日志文件轮换

如果 audit_log_rotate_on_size 为 0(默认值),则除非手动执行,否则不会发生日志轮换。

要手动轮换审计日志文件,请运行 SELECT audit_log_rotate(); 来重命名当前审计日志文件并打开新的审计日志文件。文件将根据 审计日志文件的命名约定 中描述的约定重命名。

使用 audit_log_rotate() 函数需要 AUDIT_ADMIN 权限。

管理已存档日志文件(已重命名的文件)的数量及其使用的空间是一项手动任务,涉及从您的文件系统中删除不再需要的已存档审计日志文件。

使用 audit_log_rotate() 函数重命名的审计日志文件的内容可以通过 audit_log_read() 函数读取。

手动审计日志文件轮换(旧方法)
注意

audit_log_flush 变量和这种审计日志文件轮换方法已弃用;预计在 MySQL 的未来版本中将删除对它的支持。

如果 audit_log_rotate_on_size 为 0(默认值),则除非手动执行,否则不会发生日志轮换。在这种情况下,当 audit_log_flush 值从禁用更改为启用时,审计日志插件会关闭并重新打开日志文件。日志文件重命名必须在服务器外部完成。假设日志文件名是 audit.log,并且您想保留三个最新的日志文件,在 audit.log.1audit.log.3 的名称之间循环。在 Unix 上,像这样手动执行轮换

  1. 从命令行重命名当前日志文件

    mv audit.log.2 audit.log.3
    mv audit.log.1 audit.log.2
    mv audit.log audit.log.1

    此策略会覆盖当前 audit.log.3 内容,对已存档日志文件数量及其使用的空间进行限制。

  2. 此时,插件仍在写入当前日志文件,该文件已重命名为 audit.log.1。连接到服务器并刷新日志文件,以便插件关闭它并重新打开新的 audit.log 文件

    SET GLOBAL audit_log_flush = ON;

    audit_log_flush 是特殊的,因为它的值仍然是 OFF,因此您不需要在再次启用它之前明确禁用它来执行另一个刷新。

注意

如果启用压缩或加密,则日志文件名将包含表示已启用功能的后缀,以及加密启用时的密码 ID。如果文件名包含密码 ID,请确保在手动重命名的任何文件中保留 ID,以便可以确定用于解密操作的密码。

注意

对于 JSON 格式的日志记录,手动重命名审计日志文件会使它们无法使用日志读取函数,因为审计日志插件无法再确定它们是日志文件序列的一部分(请参阅 第 8.4.5.6 节,“读取审计日志文件”)。考虑将 audit_log_rotate_on_size 设置为大于 0,以改为使用基于大小的轮换。

自动审计日志文件轮换

如果 audit_log_rotate_on_size 大于 0,则设置 audit_log_flush 不会产生影响。相反,每当写入当前日志文件导致其大小超过 audit_log_rotate_on_size 值时,审计日志插件会自动重命名当前日志文件,并使用原始名称打开新的当前日志文件。

在以下情况下也会发生自动基于大小的轮换

插件通过在基本名称后插入时间戳来重命名原始文件。例如,如果文件名是 audit.log,则插件会将其重命名为 audit.20210115T140633.log 等值。时间戳是 YYYYMMDDThhmmss 格式的 UTC 值。对于 XML 日志记录,时间戳指示轮换时间。对于 JSON 日志记录,时间戳是写入文件的最后一个事件的时间戳。

如果日志文件已加密,则原始文件名已包含指示加密密码创建时间的时间戳(请参阅 审计日志文件的命名约定)。在这种情况下,轮换后的文件名包含两个时间戳。例如,已加密的日志文件名为 audit.log.20210110T130749-1.enc,它将重命名为 audit.20210115T140633.log.20210110T130749-1.enc 等值。

审计日志文件修剪

审计日志插件支持修剪已轮换的 JSON 格式的审计日志文件,如果启用了自动日志文件轮换。要使用此功能

  • audit_log_format 设置为 JSON。(此外,还可以考虑更改 audit_log_file;请参阅 选择审计日志文件格式。)

  • audit_log_rotate_on_size 设置为大于 0,以指定自动日志文件轮换发生的大小(以字节为单位)。

  • 默认情况下,不会修剪自动轮换的 JSON 格式的日志文件。要启用修剪,请将以下系统变量之一设置为大于 0 的值

    • audit_log_max_size 设置为大于 0,以指定已轮换日志文件的组合大小限制,超过此限制后,这些文件将成为修剪的目标。

    • audit_log_prune_seconds 设置为大于 0,以指定已轮换日志文件成为修剪目标的秒数。

    audit_log_max_sizeaudit_log_prune_seconds 都大于 0 时,audit_log_max_size 的值优先级高于 audit_log_prune_seconds。如果插件初始化时这两个参数都大于 0,则会向服务器错误日志写入警告信息。如果客户端在运行时将这两个参数都设置为大于 0,则会返回警告信息给客户端。

    注意

    写入错误日志的警告信息以“Note”形式显示,属于信息类消息。为了确保这些信息出现在错误日志中并且不会被丢弃,请确保错误日志记录的详细程度足够包含信息类消息。例如,如果您使用的是基于优先级的日志过滤,如 第 7.4.2.5 节,“基于优先级的错误日志过滤 (log_filter_internal)” 中所述,将 log_error_verbosity 系统变量设置为 3。

如果启用了 JSON 格式的日志文件修剪,则按以下方式进行。

对于基于合并的轮转日志文件大小的修剪,如果合并的大小超过了 audit_log_max_size 指定的限制,则审计日志插件会删除最旧的文件,直到它们的合并大小不超过限制为止。

对于基于轮转日志文件年龄的修剪,修剪点是当前时间减去 audit_log_prune_seconds 的值。在轮转的 JSON 格式的日志文件中,每个文件名的时间戳部分表示写入文件的最后一个事件的时间戳。审计日志插件使用文件名时间戳来确定哪些文件只包含比修剪点更旧的事件,并删除它们。

审计日志写入策略

审计日志插件可以使用多种策略进行日志写入。无论采用哪种策略,日志记录都是尽力而为的,不保证一致性。

要指定写入策略,请在服务器启动时设置 audit_log_strategy 系统变量。默认情况下,策略值为 ASYNCHRONOUS,插件会异步写入缓冲区,如果缓冲区已满,则等待。您可以告诉插件不要等待 (PERFORMANCE) 或同步写入,可以使用文件系统缓存 (SEMISYNCHRONOUS) 或在每次写入请求后强制执行 sync() 调用 (SYNCHRONOUS)。

在很多情况下,如果当前查询太大,无法放入缓冲区,则插件会直接写入 JSON 格式的审计日志。写入策略决定了插件如何增加直接写入计数。您可以使用 Audit_log_direct_writes 状态变量跟踪直接写入的次数。

对于异步写入策略,audit_log_buffer_size 系统变量表示缓冲区大小(以字节为单位)。在服务器启动时设置此变量以更改缓冲区大小。插件使用单个缓冲区,并在初始化时分配缓冲区,并在终止时删除缓冲区。插件不会为非异步写入策略分配此缓冲区。

异步日志记录策略具有以下特点:

  • 对服务器性能和可扩展性的影响最小。

  • 生成审计事件的线程被阻塞的最短时间;即分配缓冲区的时间加上将事件复制到缓冲区的时间。

  • 输出到缓冲区。一个单独的线程处理从缓冲区到日志文件的写入。

使用异步日志记录,如果在写入文件期间发生问题,或者插件未正常关闭(例如,服务器主机意外退出),则日志文件的完整性可能会受到影响。要降低此风险,请将 audit_log_strategy 设置为使用同步日志记录。

PERFORMANCE 策略的缺点是,如果缓冲区已满,它会丢弃事件。对于负载很高的服务器,审计日志可能缺少事件。