二进制日志包含“事件”,这些事件描述数据库更改,例如表创建操作或表数据更改。它还包含对可能已进行更改的语句的事件(例如,DELETE
匹配的行),除非使用基于行的日志记录。二进制日志还包含有关更新数据的每个语句执行时间的信息。二进制日志具有两个重要用途
对于复制,复制源服务器上的二进制日志提供了要发送到副本的数据更改的记录。源服务器将其二进制日志中包含的信息发送到其副本,这些副本将重现这些事务以进行与源服务器相同的更改。参见 第 19.2 节,“复制实现”.
某些数据恢复操作需要使用二进制日志。在恢复备份后,重新执行备份后记录在二进制日志中的事件。这些事件使数据库从备份时点更新。参见 第 9.5 节,“时间点(增量)恢复”.
二进制日志不用于不修改数据的语句,例如 SELECT
或 SHOW
。要记录所有语句(例如,要识别问题查询),请使用通用查询日志。参见 第 7.4.3 节,“通用查询日志”.
启用二进制日志记录的服务器运行速度会略微变慢。但是,二进制日志在启用复制和恢复操作方面的优势通常超过这种轻微的性能下降。
二进制日志对意外停止具有弹性。只有完整的事件或事务会被记录或读回。
写入二进制日志的语句中的密码会由服务器重写,不会以纯文本的形式出现。另见 第 8.1.2.3 节,“密码和日志记录”.
MySQL 二进制日志文件和中继日志文件可以加密,有助于保护这些文件以及它们可能包含的敏感数据免遭外部攻击者的滥用,以及免遭存储这些文件的操作系统的用户的未经授权的查看。您可以通过将 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
选项且没有字符串或字符串为空,则基文件名默认为
,使用主机名。建议指定基文件名,这样即使主机名发生更改,也可以轻松继续使用相同的二进制日志文件名(参见 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
使用。
当启用二进制日志记录时,服务器可以使用默认的服务器 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 节,“二进制日志记录格式”。
服务器以与处理 --replicate-do-db
和 --replicate-ignore-db
选项相同的方式评估 --binlog-do-db
和 --binlog-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。
如果使用二进制日志和基于行的日志记录,则对于 CREATE ... SELECT
或 INSERT ... SELECT
语句,并发插入将转换为普通插入。这样做是为了确保在备份操作期间应用日志时,可以重新创建表格的精确副本。如果使用基于语句的日志记录,则原始语句将写入日志。
二进制日志格式有一些已知的限制,这些限制会影响从备份中恢复。请参阅 第 19.5.1 节,“复制功能和问题”。
存储程序的二进制日志记录按 第 27.7 节,“存储程序二进制日志记录” 中所述进行。
请注意,由于复制方面的增强,MySQL 8.4 中的二进制日志格式与以前版本的 MySQL 不同。请参阅 第 19.5.2 节,“MySQL 版本之间的复制兼容性”。
如果服务器无法写入二进制日志、刷新二进制日志文件或将二进制日志同步到磁盘,则复制源服务器上的二进制日志可能会变得不一致,副本可能会失去与源的同步。系统变量 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
设置为 1,如果发生崩溃,表格内容和二进制日志内容之间也可能会出现不一致。例如,如果您使用的是 InnoDB
表,并且 MySQL 服务器处理 COMMIT
语句,它会按顺序将许多准备好的事务写入二进制日志,同步二进制日志,然后将事务提交到 InnoDB
。如果服务器在两次操作之间意外退出,则该事务会在重新启动时被 InnoDB
回滚,但仍会存在于二进制日志中。在以前的版本中,通过在 XA 事务中启用 InnoDB
对两阶段提交的支持来解决此问题。在 MySQL 8.4 中,始终启用 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
以下系统变量的会话值将写入二进制日志,并在副本解析二进制日志时由副本执行