Documentation Home

5.4.4 二进制日志

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

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

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

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

运行启用了二进制日志记录的服务器会使性能稍微变慢。但是,二进制日志在使您能够设置复制和恢复操作方面的好处通常超过这种微小的性能下降。

二进制日志对意外停止具有弹性。仅记录或回读完整的事件或事务。

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

从 MySQL 8.0.14 开始,二进制日志文件和中继日志文件可以被加密,有助于保护这些文件和其中包含的潜在敏感数据不被外部攻击者滥用,也不会被操作系统用户未经授权查看被存储。binlog_encryption您可以通过将系统变量设置为 来在 MySQL 服务器上启用加密 ON。有关详细信息,请参阅 第 17.3.2 节,“加密二进制日志文件和中继日志文件”

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

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

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

--log-slave-updates选项 --slave-preserve-commit-order 需要二进制日志记录。如果禁用二进制日志记录,请忽略这些选项,或指定 --log-slave-updates=OFFand --skip-slave-preserve-commit-order。 指定--skip-log-bin 或 时,MySQL 默认禁用这些选项 。--disable-log-bin如果您将 or 与 or 一起指定 , --log-slave-updates则会 --slave-preserve-commit-order 发出 警告或错误消息。 --skip-log-bin--disable-log-bin

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

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

  • 服务器已启动或重新启动

  • 服务器刷新日志。

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

二进制日志文件可能会比 max_binlog_size使用大型事务时更大,因为事务是整体写入文件的,从不在文件之间拆分。

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

术语二进制日志文件通常表示包含数据库事件的单独编号文件。术语 二进制日志共同表示一组编号的二进制日志文件加上索引文件。

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

在 MySQL 5.7 中,启用二进制日志记录时必须指定服务器 ID,否则服务器将无法启动。在 MySQL 8.0 中,server_id 系统变量默认设置为 1。启用二进制日志记录时,服务器可以使用此默认 ID 启动,但如果您未使用server_id 系统变量明确指定服务器 ID,则会发出一条信息性消息。对于复制拓扑中使用的服务器,您必须为每个服务器指定一个唯一的非零服务器 ID。

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

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

二进制日志中记录的事件的格式取决于二进制日志记录格式。支持三种格式类型:基于行的日志记录、基于语句的日志记录和混合基础日志记录。使用的二进制日志记录格式取决于 MySQL 版本。有关日志记录格式的一般描述,请参阅 第 5.4.4.1 节,“二进制日志记录格式”。有关二进制日志格式的详细信息,请参阅 MySQL Internals: The Binary Log

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

副本以系统变量 log_replica_updates(从 MySQL 8.0.26 开始)或log_slave_updates (在 MySQL 8.0.26 之前)默认启用,这意味着副本将从源接收到的任何数据修改写入其自己的二进制日志。必须启用二进制日志才能使此设置起作用(请参阅 第 17.1.6.3 节,“副本服务器选项和变量”)。此设置使副本能够充当其他副本的源。

您可以使用语句删除所有二进制日志文件 RESET MASTER,或使用PURGE BINARY LOGS. 请参阅 第 13.7.8.6 节,“RESET 语句”第 13.4.1.1 节,“PURGE BINARY LOGS 语句”

如果你正在使用复制,你不应该删除源上的旧二进制日志文件,直到你确定没有副本仍然需要使用它们。例如,如果您的副本永远不会落后三天以上,您可以每天一次在源上执行mysqladmin flush-logs,然后删除任何超过三天的日志。您可以手动删除文件,但最好使用PURGE BINARY LOGS,它还可以为您安全地更新二进制日志索引文件(并且可以采用日期参数)。参见 第 13.4.1.1 节,“PURGE BINARY LOGS 语句”

您可以使用mysqlbinlog实用程序 显示二进制日志文件的内容 。当您想要重新处理日志中的语句以进行恢复操作时,这会很有用。例如,您可以从二进制日志更新 MySQL 服务器,如下所示:

$> mysqlbinlog log_file | mysql -h server_name

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

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

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

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

不能回滚对非事务性表的修改。如果回滚的事务包括对非事务表的修改,则整个事务会 ROLLBACK 在末尾记录一条语句,以确保复制对这些表的修改。

当处理事务的线程启动时,它会分配一个缓冲区binlog_cache_size来缓冲语句。如果语句大于此,线程将打开一个临时文件来存储事务。临时文件在线程结束时被删除。从 MySQL 8.0.17 开始,如果服务器上的二进制日志加密处于活动状态,则临时文件将被加密。

Binlog_cache_usestatus 变量显示使用此缓冲区(可能还有临时文件)存储语句的事务数 。status 变量显示这些 Binlog_cache_disk_use事务中有多少实际上必须使用临时文件。这两个变量可用于调整 binlog_cache_size到足够大的值以避免使用临时文件。

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

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

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

存储程序的二进制日志记录按照 第 25.7 节,“存储程序二进制日志记录”中的描述完成。

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

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

  • 默认设置ABORT_SERVER使服务器停止二进制日志记录并关闭。此时,您可以识别并更正错误的原因。重新启动时,恢复会像服务器意外停止的情况一样进行(请参阅 第 17.4.2 节,“处理副本的意外停止”)。

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

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

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

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

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

以下系统变量的会话值被写入二进制日志,并在解析二进制日志时由副本接受: