文档首页
MySQL 9.0 参考手册
相关文档 下载本手册

7.4.4 二进制日志

二进制日志包含描述数据库更改的“事件”,例如表创建操作或表数据更改。它还包含可能已经进行更改的语句的事件(例如,与任何行都不匹配的 DELETE 语句),除非使用了基于行的日志记录。二进制日志还包含有关每个更新数据的语句花费多长时间的信息。二进制日志有两个重要用途

  • 对于复制,复制源服务器上的二进制日志提供了要发送到副本的数据更改记录。源将其二进制日志中包含的信息发送到其副本,副本会复制这些事务以进行与源上相同的更改。请参阅 第 19.2 节“复制实现”

  • 某些数据恢复操作需要使用二进制日志。恢复备份后,将重新执行在创建备份后记录在二进制日志中的事件。这些事件使数据库从备份点开始更新。请参阅 第 9.5 节“时间点(增量)恢复”

二进制日志不用于 SELECTSHOW 等不修改数据的语句。要记录所有语句(例如,要识别问题查询),请使用通用查询日志。请参阅 第 7.4.3 节“通用查询日志”

运行启用了二进制日志记录的服务器会使性能略有下降。但是,二进制日志在使您能够设置复制和进行还原操作方面的优势通常超过了这种轻微的性能下降。

二进制日志可以抵抗意外停止。只有完整的事件或事务才会被记录或读取。

写入二进制日志的语句中的密码会被服务器重写,以避免以纯文本形式出现。另请参阅 第 8.1.2.3 节“密码和日志记录”

MySQL 二进制日志文件和中继日志文件可以加密,这有助于保护这些文件和其中包含的潜在敏感数据免遭外部攻击者的滥用,以及防止存储它们的 operativosystem 上的用户的未经授权的查看。您可以通过将 binlog_encryption 系统变量设置为 ON 来在 MySQL 服务器上启用加密。有关更多信息,请参阅 第 19.3.2 节“加密二进制日志文件和中继日志文件”

以下讨论描述了影响二进制日志记录操作的一些服务器选项和变量。有关完整列表,请参阅 第 19.1.6.4 节“二进制日志记录选项和变量”

默认情况下启用二进制日志记录(log_bin 系统变量设置为 ON)。例外情况是,如果您使用 mysqld 通过使用 --initialize--initialize-insecure 选项调用它来手动初始化数据目录,此时默认情况下禁用二进制日志记录,但可以通过指定 --log-bin 选项来启用。

要禁用二进制日志记录,您可以在启动时指定 --skip-log-bin--disable-log-bin 选项。如果同时指定了这两个选项中的任何一个和 --log-bin,则以后指定的选项优先。

选项 --log-replica-updates--replica-preserve-commit-order 要求使用二进制日志记录。如果禁用二进制日志记录,请省略这些选项,或指定 --log-replica-updates=OFF--skip-replica-preserve-commit-order。当指定了 --skip-log-bin--disable-log-bin 时,MySQL 默认会禁用这些选项。如果将 --log-replica-updates--replica-preserve-commit-order--skip-log-bin--disable-log-bin 一起指定,则会发出警告或错误消息。

--log-bin[=base_name] 选项用于指定二进制日志文件的基本名称。如果不提供 --log-bin 选项,MySQL 会使用 binlog 作为二进制日志文件的默认基本名称。为了与早期版本兼容,如果提供不带字符串或空字符串的 --log-bin 选项,则基本名称默认为 host_name-bin,使用主机名。建议您指定一个基本名称,以便在主机名更改时,您可以轻松地继续使用相同的二进制日志文件名(请参阅 第 B.3.7 节 “MySQL 中的已知问题”)。如果在日志名中提供扩展名(例如,--log-bin=base_name.extension),则扩展名将被静默删除并忽略。

mysqld 会将数字扩展名附加到二进制日志基本名称以生成二进制日志文件名。每次服务器创建新的日志文件时,该数字都会增加,从而创建一个有序的文件系列。每当发生以下任何事件时,服务器都会在该系列中创建一个新文件:

  • 服务器启动或重启

  • 服务器刷新日志。

  • 当前日志文件的大小达到 max_binlog_size

如果正在使用大型事务,则二进制日志文件可能会大于 max_binlog_size,因为事务会一次性写入文件,而不会拆分到多个文件中。

为了跟踪已使用哪些二进制日志文件,mysqld 还会创建一个二进制日志索引文件,其中包含二进制日志文件的名称。默认情况下,该文件与二进制日志文件具有相同的基本名称,扩展名为 '.index'。可以使用 --log-bin-index[=file_name] 选项更改二进制日志索引文件的名称。在 mysqld 运行时,不应手动编辑此文件;这样做会使 mysqld 混乱。

术语“二进制日志文件”通常是指包含数据库事件的单个编号文件。术语“二进制日志”统称为一组编号的二进制日志文件以及索引文件。

二进制日志文件和二进制日志索引文件的默认位置是数据目录。可以使用 --log-bin 选项指定备用位置,方法是在基本名称中添加一个前导绝对路径名以指定不同的目录。当服务器从二进制日志索引文件(该文件跟踪已使用的二进制日志文件)中读取条目时,它会检查该条目是否包含相对路径。如果是,则路径的相对部分将替换为使用 --log-bin 选项设置的绝对路径。记录在二进制日志索引文件中的绝对路径保持不变;在这种情况下,必须手动编辑索引文件以启用要使用的新路径。二进制日志文件基本名称和任何指定的路径都可作为 log_bin_basename 系统变量使用。

启用二进制日志记录后,可以使用默认服务器 ID 启动服务器,但如果没有使用 server_id 系统变量显式指定服务器 ID,则会发出信息性消息。对于在复制拓扑中使用的服务器,必须为每个服务器指定唯一的非零服务器 ID。

具有足够权限设置受限会话系统变量的客户端(请参阅 第 7.1.9.1 节 “系统变量权限”)可以通过使用 SET sql_log_bin=OFF 语句禁用其自身语句的二进制日志记录。

默认情况下,服务器会记录事件的长度以及事件本身,并使用它来验证事件是否已正确写入。还可以通过设置 binlog_checksum 系统变量来使服务器写入事件的校验和。从二进制日志中读取数据时,源默认使用事件长度,但可以通过启用 source_verify_checksum 来使用校验和(如果可用)。副本上的复制 I/O(接收器)线程也会验证从源接收到的事件。可以通过启用 replica_sql_verify_checksum 来使复制 SQL(应用器)线程在从中继日志读取数据时使用校验和(如果可用)。

记录在二进制日志中的事件格式取决于二进制日志记录格式。支持三种格式类型:基于行的日志记录、基于语句的日志记录和混合日志记录。使用的二进制日志记录格式取决于 MySQL 版本。有关日志记录格式的说明,请参阅 第 7.4.4.1 节 “二进制日志记录格式”

服务器评估 --binlog-do-db--binlog-ignore-db 选项的方式与其评估 --replicate-do-db--replicate-ignore-db 选项的方式相同。有关如何执行此操作的信息,请参阅 第 19.2.5.1 节 “数据库级复制和二进制日志记录选项的评估”

副本在启动时默认启用 log_replica_updates,这意味着副本会将其从源接收到的任何数据修改写入其自己的二进制日志。必须启用二进制日志才能使此设置生效(请参阅 第 19.1.6.3 节 “副本服务器选项和变量”)。此设置使副本能够充当其他副本的源。

可以使用 RESET BINARY LOGS AND GTIDS 语句删除所有二进制日志文件,或使用 PURGE BINARY LOGS 删除其中的一个子集。请参阅 第 15.7.8.6 节 “RESET 语句”第 15.4.1.1 节 “PURGE BINARY LOGS 语句”

如果正在使用 MySQL 复制,则在确定没有副本需要使用旧的二进制日志文件之前,不应删除源上的这些文件。例如,如果您的副本从不落后于主服务器三天以上,则可以每天在源上执行一次 mysqladmin flush-logs binary,然后删除所有超过三天的日志。您可以手动删除这些文件,但最好使用 PURGE BINARY LOGS,它还会为您安全地更新二进制日志索引文件(并且可以接受日期参数)。请参阅 第 15.4.1.1 节 “PURGE BINARY LOGS 语句”

可以使用 mysqlbinlog 实用程序显示二进制日志文件的内容。当您希望重新处理日志中的语句以进行恢复操作时,这将非常有用。例如,可以按如下方式从二进制日志更新 MySQL 服务器:

$> mysqlbinlog log_file | mysql -h server_name

mysqlbinlog 还可以用于显示副本上中继日志文件的内容,因为它们使用与二进制日志文件相同的格式写入。有关 mysqlbinlog 实用程序及其使用方法的更多信息,请参阅 第 6.6.9 节 “mysqlbinlog - 处理二进制日志文件的实用程序”。有关二进制日志和恢复操作的更多信息,请参阅 第 9.5 节 “时间点(增量)恢复”

二进制日志记录在语句或事务完成后立即执行,但在释放任何锁或执行任何提交之前执行。这可确保日志按提交顺序记录。

对非事务性表的更新在执行后立即存储在二进制日志中。

在未提交的事务中,所有更改事务性表(如 InnoDB 表)的更新(UPDATEDELETEINSERT)都会被缓存,直到服务器接收到 COMMIT 语句。此时,mysqld 会在执行 COMMIT 之前将整个事务写入二进制日志。

对非事务性表的修改无法回滚。如果回滚的事务包含对非事务性表的修改,则会使用末尾的 ROLLBACK 语句记录整个事务,以确保复制对这些表的修改。

当处理事务的线程启动时,它会分配一个大小为 binlog_cache_size 的缓冲区来缓冲语句。如果语句大于此值,则线程将打开一个临时文件来存储事务。该临时文件将在线程结束后删除。如果服务器上启用了二进制日志加密,则会对临时文件进行加密。

状态变量 Binlog_cache_use 显示了使用此缓冲区(以及可能的临时文件)存储语句的事务数。状态变量 Binlog_cache_disk_use 显示了其中实际需要使用临时文件的事务数。可以使用这两个变量将 binlog_cache_size 调整到足够大的值,以避免使用临时文件。

系统变量 max_binlog_cache_size(默认值为 4GB,也是最大值)可用于限制用于缓存多语句事务的总大小。如果事务大于此字节数,则会失败并回滚。最小值为 4096。

如果您正在使用二进制日志和基于行的日志记录,则对于 CREATE ... SELECTINSERT ... SELECT 语句,并发插入将转换为普通插入。这样做是为了确保您可以在备份操作期间通过应用日志来重新创建表的精确副本。如果您使用的是基于语句的日志记录,则原始语句将写入日志。

二进制日志格式有一些已知的限制,可能会影响从备份中恢复。请参阅 第 19.5.1 节,“复制功能和问题”

存储程序的二进制日志记录如 第 27.8 节,“存储程序二进制日志记录” 中所述。

请注意,由于复制功能的增强,MySQL 9.0 中的二进制日志格式与以前版本的 MySQL 不同。请参阅 第 19.5.2 节,“MySQL 版本之间的复制兼容性”

如果服务器无法写入二进制日志、刷新二进制日志文件或将二进制日志同步到磁盘,则复制源服务器上的二进制日志可能会变得不一致,并且副本可能会失去与源的同步。 binlog_error_action 系统变量控制在二进制日志遇到此类错误时要采取的操作。

  • 默认设置 ABORT_SERVER 会使服务器停止二进制日志记录并关闭。此时,您可以确定并纠正错误原因。重新启动后,恢复过程与意外服务器停机的恢复过程相同(请参阅 第 19.4.2 节,“处理副本的意外停止”)。

  • 设置 IGNORE_ERROR 提供了与旧版本 MySQL 的向后兼容性。使用此设置,服务器将继续进行中的事务并记录错误,然后停止二进制日志记录,但继续执行更新。此时,您可以确定并纠正错误原因。要恢复二进制日志记录,必须再次启用 log_bin,这需要重新启动服务器。仅当您需要向后兼容性并且二进制日志在此 MySQL 服务器实例上不是必需的时,才使用此选项。例如,您可能仅将二进制日志用于服务器的间 Auditing 或调试,而不用于从服务器进行复制或依赖它进行时间点还原操作。

默认情况下,二进制日志在每次写入时都会同步到磁盘(sync_binlog=1)。如果未启用 sync_binlog,并且操作系统或机器(不仅仅是 MySQL 服务器)崩溃,则二进制日志的最后语句可能会丢失。为防止这种情况,请启用 sync_binlog 系统变量,以便在每 N 个提交组之后将二进制日志同步到磁盘。请参阅 第 7.1.8 节,“服务器系统变量”sync_binlog 的最安全值为 1(默认值),但这也是最慢的值。

在早期版本的 MySQL 中,即使将 sync_binlog 设置为 1,如果发生崩溃,表内容和二进制日志内容之间也可能会出现不一致的情况。例如,如果您使用的是 InnoDB 表,并且 MySQL 服务器正在处理 COMMIT 语句,它会将许多准备好的事务按顺序写入二进制日志,同步二进制日志,然后将事务提交到 InnoDB。如果服务器在这两个操作之间意外退出,则事务将在重新启动时由 InnoDB 回滚,但仍存在于二进制日志中。在以前的版本中,通过在 XA 事务中启用对两阶段提交的 InnoDB 支持解决了此类问题。在 MySQL 9.0 中,始终启用对 XA 事务中两阶段提交的 InnoDB 支持。

对 XA 事务中两阶段提交的 InnoDB 支持可确保二进制日志和 InnoDB 数据文件同步。但是,还应将 MySQL 服务器配置为在提交事务之前将二进制日志和 InnoDB 日志同步到磁盘。默认情况下会同步 InnoDB 日志,并且 sync_binlog=1 可确保同步二进制日志。隐式 InnoDB 对 XA 事务中两阶段提交的支持和 sync_binlog=1 的作用是,在崩溃后重新启动时,在回滚事务之后,MySQL 服务器会扫描最新的二进制日志文件以收集事务 xid 值并计算二进制日志文件中的最后一个有效位置。然后,MySQL 服务器会指示 InnoDB 完成已成功写入二进制日志的所有已准备好的事务,并将二进制日志截断为最后一个有效位置。这可确保二进制日志反映 InnoDB 表的确切数据,因此副本与源保持同步,因为它不会收到已回滚的语句。

如果 MySQL 服务器在崩溃恢复时发现二进制日志比预期的短,则它缺少至少一个已成功提交的 InnoDB 事务。如果 sync_binlog=1 并且磁盘/文件系统在被请求时执行实际同步(有些则不会),则不应该发生这种情况,因此服务器会打印错误消息 二进制日志 file_name 比预期的大小短。在这种情况下,此二进制日志不正确,应从源数据的全新快照重新启动复制。

以下系统变量的会话值将写入二进制日志,并在副本解析二进制日志时由副本遵循