二进制日志包含描述数据库更改的事件,例如表创建操作或表数据更改。它还包含可能会更改的语句的事件(例如,一个没有匹配行的 DELETE
),除非使用基于行的日志记录。二进制日志还包含每个语句执行的时间信息。二进制日志有两个重要的用途:
-
对于复制,源服务器上的二进制日志提供了要发送到副本的数据更改记录。源服务器将其二进制日志中的信息发送到副本,副本将重复这些事务,以便在源服务器上进行相同的数据更改。见 第 19.2 节,“复制实现”。
-
某些数据恢复操作需要使用二进制日志。在备份恢复后,二进制日志中记录的事件将被重新执行,这些事件将数据库恢复到备份点。见 第 9.5 节,“点时间恢复”。
二进制日志不用于不修改数据的语句,例如 SELECT
或 SHOW
。要记录所有语句(例如,来标识问题查询),请使用通用查询日志。见 第 7.4.3 节,“通用查询日志”。
启用二进制日志记录的服务器性能会略有下降。但是,二进制日志在启用复制和恢复操作方面的益处通常超过这微小的性能下降。
二进制日志对意外停止具有弹性。只有完整的事件或事务被记录或读回。
写入二进制日志的语句中的密码将被服务器重写,不会以明文形式出现。另见第 8.1.2.3 节,“密码和日志记录”。
MySQL 二进制日志文件和中继日志文件可以被加密,以保护这些文件和其中包含的敏感数据免受外部攻击者的滥用,以及未经授权的查看操作系统中的用户。您可以通过将 binlog_encryption
系统变量设置为 ON
来启用服务器上的加密。更多信息,请参见第 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
。MySQL 在禁用二进制日志记录时默认禁用这些选项,例如指定 --skip-log-bin
或 --disable-log-bin
。如果您指定 --log-replica-updates
或 --replica-preserve-commit-order
与 --skip-log-bin
或 --disable-log-bin
一起,会发出警告或错误消息。
选项 --log-bin[=
用于指定二进制日志文件的基本名称。如果您不提供 base_name
]--log-bin
选项,MySQL 将使用 binlog
作为二进制日志文件的默认基本名称。为了与早期版本兼容,如果您提供 --log-bin
选项但不提供字符串或提供空字符串,基本名称将默认为
,使用主机机器的名称。建议您指定基本名称,以便在主机名称更改时可以继续使用相同的二进制日志文件名称(见 B.3.7 节,“MySQL 中的已知问题”)。如果您在日志名称中提供扩展名(例如,host_name
-bin--log-bin=
),扩展名将被默默地删除并忽略。base_name.extension
mysqld 将数字扩展名追加到二进制日志基本名称,以生成二进制日志文件名称。数字每次服务器创建新日志文件时增加,从而创建一个有序的文件系列。服务器在以下事件发生时创建新文件:
-
服务器启动或重新启动
-
服务器刷新日志。
-
当前日志文件的大小达到
max_binlog_size
。
二进制日志文件可能会变得比 max_binlog_size
大,因为您使用大事务,因为事务作为一个整体写入文件,从不分割文件。
为了跟踪哪些二进制日志文件已经被使用,mysqld 还创建了一个二进制日志索引文件,该文件包含二进制日志文件的名称。默认情况下,该文件具有与二进制日志文件相同的基本名称,扩展名为 '.index'
。您可以使用 --log-bin-index[=
选项更改二进制日志索引文件的名称。在 mysqld 运行时,不要手动编辑该文件;这样做将混淆 mysqld。file_name
]
术语 “二进制日志文件” 通常指的是包含数据库事件的单个编号文件。术语 “二进制日志” 集体地指的是编号的二进制日志文件加上索引文件。
二进制日志文件和二进制日志索引文件的默认位置是数据目录。您可以使用 --log-bin
选项指定备用位置,方法是将基本名称的绝对路径名添加到基本名称中,以指定不同的目录。当服务器从二进制日志索引文件中读取条目时,该文件跟踪已使用的二进制日志文件,它检查条目是否包含相对路径。如果是,则相对路径部分将被替换为使用 --log-bin
选项设置的绝对路径。记录在二进制日志索引文件中的绝对路径保持不变;在这种情况下,索引文件必须手动编辑以启用新的路径或路径。二进制日志文件的基本名称和任何指定的路径都可以作为 log_bin_basename
系统变量。
在 MySQL 5.7 中,当启用二进制日志记录时,必须指定服务器 ID,否则服务器将不会启动。在 MySQL 8.3 中,server_id
系统变量默认设置为 1。启用二进制日志记录时,可以使用默认 ID 启动服务器,但如果您不明确指定服务器 ID,则会发出信息性消息。对于在复制拓扑结构中使用的服务器,您必须为每个服务器指定唯一的非零服务器 ID。
具有足够权限设置受限会话系统变量(见 第 7.1.9.1 节,“系统变量权限”)的客户端可以使用 SET sql_log_bin=OFF
语句禁用自己的语句的二进制日志记录。
默认情况下,服务器记录事件的长度以及事件本身,并使用该信息来验证事件是否正确写入。你也可以通过设置binlog_checksum
系统变量,导致服务器为事件写入校验和。当从二进制日志中读取时,默认情况下使用事件长度,但可以通过启用source_verify_checksum
来使用校验和。复制I/O(receiver)线程在副本上也验证来自源的事件。你可以通过启用replica_sql_verify_checksum
,使复制SQL(applier)线程在从中继日志中读取时使用校验和。
记录在二进制日志中的事件格式取决于二进制日志格式。支持三种格式类型:基于行的日志记录、基于语句的日志记录和混合日志记录。使用的二进制日志格式取决于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
表)的所有更新(UPDATE
、DELETE
或 INSERT
)将被缓存,直到服务器收到 COMMIT
语句时。在那时,mysqld 将整个事务写入二进制日志,然后执行 COMMIT
。
无法回滚非事务表中的修改。如果回滚的事务包括非事务表中的修改,整个事务将以ROLLBACK
语句结尾,以确保这些表中的修改被复制。
当处理事务的线程启动时,它会分配一个binlog_cache_size
大小的缓冲区来缓存语句。如果语句大于这个大小,线程将打开一个临时文件来存储事务。临时文件将在线程结束时删除。如果服务器上启用了二进制日志加密,临时文件将被加密。
状态变量Binlog_cache_use
显示了使用这个缓冲区(可能还有临时文件)来存储语句的交易数量。状态变量Binlog_cache_disk_use
显示了这些交易中实际使用临时文件的数量。这些两个变量可以用于调整binlog_cache_size
的值,以避免使用临时文件。
系统变量max_binlog_cache_size
(默认为4GB,也是最大值)可以用于限制多语句事务的缓存大小。如果事务大于这个大小,它将失败并回滚。最小值为4096。
如果您使用二进制日志和基于行的日志记录,concurrent inserts 将被转换为普通插入,以便在备份操作期间重新创建表的精确副本。如果您使用基于语句的日志记录,原始语句将被写入日志。
二进制日志格式有一些已知的限制,这些限制可能会影响备份恢复。请参阅第 19.5.1 节,“复制功能和问题”。
存储程序的二进制日志记录按照第 27.7 节,“存储程序二进制日志记录”所述进行。
注意,MySQL 8.3 中的二进制日志格式与之前的 MySQL 版本不同,这是由于复制功能的增强。请参阅第 19.5.2 节,“复制版本之间的兼容性”。
如果服务器无法写入二进制日志、刷新二进制日志文件或将二进制日志同步到磁盘,复制源服务器上的二进制日志可能会变得不一致,副本可能会与源失去同步。binlog_error_action
系统变量控制了在遇到这种错误时采取的操作。
-
默认设置:
ABORT_SERVER
,使服务器停止二进制日志记录并关闭。在此点上,您可以识别和纠正错误的原因。在重新启动时,恢复将如同意外服务器停止一样(见第 19.4.2 节,“处理副本意外停止”)。 -
设置
IGNORE_ERROR
提供了与旧版本 MySQL 的向后兼容性。使用此设置,服务器将继续当前事务并记录错误,然后停止二进制日志记录,但继续执行更新。在此点上,您可以识别和纠正错误的原因。要恢复二进制日志记录,log_bin
必须重新启用,这需要服务器重新启动。仅当您需要向后兼容性,并且二进制日志在此 MySQL 服务器实例上不是必需的时,才使用此选项。例如,您可能仅使用二进制日志进行间歇性审核或调试服务器,而不使用它进行服务器复制或依赖它进行点时间还原操作。
默认情况下,二进制日志将在每次写入时同步到磁盘上(sync_binlog=1
)。如果 sync_binlog
未启用,并且操作系统或机器(不仅是 MySQL 服务器)崩溃了,那么最后的二进制日志语句可能会丢失。要防止这种情况,启用 sync_binlog
系统变量,以便在每 N
个提交组后同步二进制日志到磁盘。见 第 7.1.8 节,“服务器系统变量”。 sync_binlog
的最安全值为 1(默认值),但这也是最慢的。
在早期的 MySQL 版本中,即使启用了 sync_binlog
,如果崩溃也可能会出现表内容和二进制日志内容之间的不一致。例如,如果您使用 InnoDB
表,并且 MySQL 服务器处理 COMMIT
语句,它将写入许多准备事务到二进制日志中,然后同步二进制日志,然后提交事务到 InnoDB
中。如果服务器在这两个操作之间意外退出,事务将被 InnoDB
回滚,但仍然存在于二进制日志中。这种问题在以前的版本中通过启用 InnoDB
对 XA 事务的两阶段提交支持来解决。在 MySQL 8.3 中,InnoDB
对 XA 事务的两阶段提交支持始终启用。
InnoDB
在XA事务中的两阶段提交支持确保二进制日志和 InnoDB
数据文件同步。然而,MySQL服务器也应该配置为在提交事务之前将二进制日志和 InnoDB
日志同步到磁盘。 InnoDB
日志默认情况下是同步的,而 sync_binlog=1
确保二进制日志同步。 InnoDB
对XA事务的隐式两阶段提交支持和 sync_binlog=1
的效果是在崩溃后重新启动时,MySQL服务器会扫描最新的二进制日志文件,以收集事务 xid
值并计算二进制日志文件的最后一个有效位置。然后,MySQL服务器会告诉 InnoDB
完成已经成功写入二进制日志的准备事务,并截断二进制日志到最后一个有效位置。这确保了二进制日志反映了 InnoDB
表的确切数据,因此副本保持与源的同步,因为它不会收到已经回滚的语句。
如果 MySQL 服务器在崩溃恢复时发现二进制日志比预期短,缺少至少一个成功提交的 InnoDB
事务。这不应该发生,如果 sync_binlog=1
并且磁盘/文件系统在请求时执行实际同步(一些不这样做),因此服务器会打印错误消息 二进制日志
。在这种情况下,该二进制日志不正确,复制应该从源数据的新快照重新启动。file_name
比预期短
以下系统变量的会话值将被写入二进制日志,并被副本在解析二进制日志时尊重: