5.4.4 二进制日志

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

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

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

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

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

二进制日志通常对意外停止具有弹性,因为只记录或回读完整的事务。有关详细信息,请参阅 第 17.3.2 节,“处理副本服务器的意外停止”

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

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

要启用二进制日志,请使用该 选项启动服务器。如果没有给出值,则默认名称是 选项的值(默认情况下是主机的名称)后跟. 如果给出了基本名称,则服务器将文件写入数据目录,除非给出基本名称和前导绝对路径名以指定不同的目录。建议您显式指定基本名称,而不是使用主机名的默认值;有关原因,请参阅第 B.3.7 节,“MySQL 中的已知问题”--log-bin[=base_name]base_name--pid-file-bin

如果您在日志名称中提供扩展名(例如, ),该扩展名将被静默删除并忽略。 --log-bin=base_name.extension

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

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

  • 服务器刷新日志。

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

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

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

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

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

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

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

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

默认情况下,复制副本服务器不会将从复制源接收到的任何数据修改写入其自己的二进制日志。要记录这些修改,--log-slave-updates除了 option 之外,还要使用option 启动副本--log-bin(请参阅第 17.1.4.3 节,“副本服务器选项和变量”)。当一个副本还充当链式复制中其他副本的源时,就会完成此操作。

您可以使用语句删除所有二进制日志文件 RESET MASTER,或使用PURGE BINARY LOGS. 请参阅 第 13.7.6.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.8 节,“mysqlbinlog — 处理二进制日志文件的实用程序”。有关二进制日志和恢复操作的更多信息,请参阅 第 7.5 节,“使用二进制日志进行时间点(增量)恢复”

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

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

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

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

当处理事务的线程启动时,它会分配一个缓冲区binlog_cache_size来缓冲语句。如果语句大于此,线程将打开一个临时文件来存储事务。临时文件在线程结束时被删除。

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

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

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

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

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

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

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

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

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

默认情况下,二进制日志不会在每次写入时同步到磁盘。因此,如果操作系统或机器(不仅是 MySQL 服务器)崩溃,二进制日志的最后语句有可能丢失。为防止这种情况,请 在每次提交组sync_binlog后使用系统变量将二进制日志同步到磁盘 。N请参阅 第 5.1.7 节,“服务器系统变量”。最安全的值为 sync_binlog1,但这也是最慢的。即使 sync_binlog设置为 1,在发生崩溃时表内容和二进制日志内容之间仍然存在不一致的可能性。

比如你在使用InnoDB表,MySQL服务器处理一条COMMIT 语句,它会将很多准备好的事务依次写入二进制日志,同步二进制日志,然后将这个事务提交到InnoDB. 如果服务器在这两个操作之间意外退出,事务将在重启时回滚,InnoDB但仍存在于二进制日志中。假设解决了这样的问题 --innodb_support_xa设置为 1,默认值。这个选项虽然与InnoDB对XA事务的支持有关,但也保证了二进制日志和InnoDB数据文件的同步。为使此选项提供更大程度的安全性,MySQL 服务器还应配置为 InnoDB在提交事务之前将二进制日志和日志同步到磁盘。日志默认是同步的InnoDBsync_binlog=1可以用来同步二进制日志。这个选项的作用是在崩溃后重启时,在做事务回滚后,MySQL服务器扫描最新的二进制日志文件来收集事务xid值并计算二进制日志文件中的最后一个有效位置。然后 MySQL 服务器通知InnoDB完成任何已成功写入二进制日志的准备事务,并将二进制日志截断到最后一个有效位置。这确保二进制日志反映 InnoDB表的准确数据,因此副本与源保持同步,因为它没有收到已回滚的语句。

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

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