MySQL8 中文参考(七十八)
原文:
dev.mysql.com/doc/refman/8.0/en/replication-options-binary-log.html
19.1.6.4 二进制日志选项和变量
-
启动时与二进制日志一起使用的选项
-
与二进制日志一起使用的系统变量
您可以使用本节中描述的mysqld选项和系统变量来影响二进制日志的操作,以及控制写入二进制日志的语句。有关二进制日志的其他信息,请参见第 7.4.4 节,“二进制日志”。有关使用 MySQL 服务器选项和系统变量的其他信息,请参见第 7.1.7 节,“服务器命令选项”和第 7.1.8 节,“服务器系统变量”。
启动时与二进制日志一起使用的选项
以下列表描述了启用和配置二进制日志的启动选项。稍后在本节中讨论与二进制日志一起使用的系统变量。
-
--binlog-row-event-max-size=*N*命令行格式 --binlog-row-event-max-size=#系统变量 (≥ 8.0.14) binlog_row_event_max_size作用域 (≥ 8.0.14) 全局 动态 (≥ 8.0.14) 否 SET_VAR提示适用 (≥ 8.0.14)否 类型 整数 默认值 8192最小值 256最大值 (64 位平台) 18446744073709551615最大值 (32 位平台) 4294967295单位 字节 当使用基于行的二进制日志记录时,此设置是行级二进制日志事件的最大大小软限制,以字节为单位。在可能的情况下,存储在二进制日志中的行被分组为大小不超过此设置值的事件。如果无法拆分事件,则最大大小可能会超过。该值必须是(否则会被四舍五入为)256 的倍数。默认值为 8192 字节。
-
命令行格式 --log-bin=file_name类型 文件名 指定用于二进制日志文件的基本名称。启用二进制日志记录后,服务器将所有更改数据的语句记录到二进制日志中,用于备份和复制。二进制日志是具有基本名称和数字扩展的文件序列。
--log-bin选项值是日志序列的基本名称。服务器通过向基本名称添加数字后缀来按顺序创建二进制日志文件。如果不提供
--log-bin选项,MySQL 将使用binlog作为二进制日志文件的默认基本名称。为了与早期版本兼容,如果提供了--log-bin选项但没有字符串或为空字符串,则基本名称默认为*host_name*-bin,使用主机机器的名称。二进制日志文件的默认位置是数据目录。您可以使用
--log-bin选项指定另一个位置,通过在基本名称前添加一个绝对路径名来指定不同的目录。当服务器从跟踪已使用的二进制日志文件的二进制日志索引文件中读取条目时,它会检查条目是否包含相对路径。如果包含相对路径,则使用--log-bin选项设置的绝对路径将替换路径的相对部分。在二进制日志索引文件中记录的绝对路径保持不变;在这种情况下,必须手动编辑索引文件以启用新路径或路径的使用。二进制日志文件基本名称和任何指定的路径可作为log_bin_basename系统变量使用。在早期的 MySQL 版本中,默认情况下禁用了二进制日志记录,只有在指定了
--log-bin选项时才会启用。从 MySQL 8.0 开始,默认情况下启用了二进制日志记录,无论您是否指定了--log-bin选项。唯一的例外是,如果您使用mysqld手动初始化数据目录,通过使用--initialize或--initialize-insecure选项调用它时,默认情况下会禁用二进制日志记录。在这种情况下,可以通过指定--log-bin选项来启用二进制日志记录。当启用二进制日志记录时,显示服务器上二进制日志记录状态的log_bin系统变量将设置为 ON。要禁用二进制日志记录,您可以在启动时指定
--skip-log-bin或--disable-log-bin选项。如果指定了其中任何一个选项,并且同时指定了--log-bin选项,则后面指定的选项优先。当禁用二进制日志记录时,log_bin系统变量将设置为 OFF。当服务器上使用 GTIDs 时,如果在异常关闭后重新启动服务器时禁用二进制日志记录,可能会丢失一些 GTIDs,导致复制失败。在正常关闭时,当前二进制日志文件中的 GTID 集合将保存在
mysql.gtid_executed表中。在未发生此情况的异常关闭后,在恢复过程中,GTIDs 将从二进制日志文件中添加到表中,前提是二进制日志记录仍然启用。如果在服务器重新启动时禁用了二进制日志记录,则服务器无法访问二进制日志文件以恢复 GTIDs,因此无法启动复制。在正常关闭后可以安全地禁用二进制日志记录。--log-slave-updates和--slave-preserve-commit-order选项需要二进制日志记录。如果禁用二进制日志记录,则省略这些选项,或指定--log-slave-updates=OFF和--skip-slave-preserve-commit-order。当指定--skip-log-bin或--disable-log-bin时,MySQL 默认禁用这些选项。如果同时指定--log-slave-updates或--slave-preserve-commit-order和--skip-log-bin或--disable-log-bin,将发出警告或错误消息。在 MySQL 5.7 中,启用二进制日志记录时必须指定服务器 ID,否则服务器将无法启动。在 MySQL 8.0 中,默认情况下将
server_id系统变量设置为 1。当启用二进制日志记录时,现在可以使用此默认服务器 ID 启动服务器,但如果您没有通过设置server_id系统变量显式指定服务器 ID,则会发出信息消息。对于用于复制拓扑的服务器,必须为每个服务器指定唯一的非零服务器 ID。有关二进制日志的格式和管理信息,请参阅第 7.4.4 节,“二进制日志”。
-
命令行格式 --log-bin-index=file_name系统变量 log_bin_index范围 全局 动态 否 SET_VAR提示适用否 类型 文件名 二进制日志索引文件的名称,其中包含二进制日志文件的名称。默认情况下,它具有与使用
--log-bin选项指定的二进制日志文件相同的位置和基本名称,再加上扩展名.index。如果您没有指定--log-bin,默认的二进制日志索引文件名为binlog.index。如果您指定了不带字符串或空字符串的--log-bin选项,则默认的二进制日志索引文件名为*host_name*-bin.index,使用主机机器的名称。有关二进制日志的格式和管理信息,请参见第 7.4.4 节,“二进制日志”。
语句选择选项。 下面列表中的选项影响写入二进制日志的语句,从而由复制源服务器发送到其副本。还有一些用于副本的选项,控制应该执行或忽略来自源的语句。有关详细信息,请参见第 19.1.6.3 节,“副本服务器选项和变量”。
-
--binlog-do-db=*db_name*命令行格式 --binlog-do-db=name类型 字符串 此选项对二进制日志记录的影响类似于
--replicate-do-db对复制的影响。此选项的影响取决于是否使用基于语句或基于行的日志格式,就像
--replicate-do-db的影响取决于是否使用基于语句或基于行的复制一样。您应该记住,用于记录给定语句的格式可能不一定与binlog_format的值所指示的格式相同。例如,DDL 语句如CREATE TABLE和ALTER TABLE始终作为语句记录,而不考虑生效的日志格式,因此对于--binlog-do-db的以下基于语句的规则始终适用于确定语句是否被记录。基于语句的日志记录。 只有那些默认数据库(即由
USE选择的数据库)为*db_name*的语句才会被写入二进制日志。要指定多个数据库,请多次使用此选项,每个数据库使用一次;但是,这样做不会导致跨数据库语句(例如UPDATE *some_db.some_table* SET foo='bar')在选择不同数据库(或没有数据库)时被记录。警告
要指定多个数据库,必须多次使用此选项。因为数据库名称可以包含逗号,如果提供逗号分隔的列表,则该列表被视为单个数据库的名称。
使用基于语句的日志记录时不像您期望的那样工作的示例:如果服务器使用
--binlog-do-db=sales启动,并且您发出以下语句,则UPDATE语句不会被记录:USE prices; UPDATE sales.january SET amount=amount+1000;这种“只需检查默认数据库”行为的主要原因是,仅凭语句本身很难知道是否应该复制(例如,如果您使用多表
DELETE语句或跨多个数据库操作的多表UPDATE语句)。如果没有必要,仅检查默认数据库而不是所有数据库会更快。另一个可能不明显的情况是,即使在设置选项时没有指定,给定的数据库也被复制。如果服务器使用
--binlog-do-db=sales启动,即使在设置--binlog-do-db时未包括prices,以下UPDATE语句也会被记录:USE sales; UPDATE prices.discounts SET percentage = percentage + 10;因为
sales是发出UPDATE语句时的默认数据库,所以UPDATE被记录。基于行的日志记录。 记录仅限于数据库*
db_name。只有属于db_name*的表的更改才会被记录;默认数据库对此没有影响。假设服务器使用--binlog-do-db=sales启动,并且基于行的日志记录生效,然后执行以下语句:USE prices; UPDATE sales.february SET amount=amount+100;sales数据库中february表的更改将根据UPDATE语句记录;无论是否发出了USE语句都会发生。然而,当使用基于行的日志记录格式和--binlog-do-db=sales时,以下UPDATE所做的更改不会被记录:USE prices; UPDATE prices.march SET amount=amount-25;即使
USE prices语句被更改为USE sales,UPDATE语句的效果仍不会被写入二进制日志。在基于语句的日志记录和基于行的日志记录中,关于涉及多个数据库的语句的
--binlog-do-db处理存在另一个重要区别。假设服务器是使用--binlog-do-db=db1启动的,并且执行了以下语句:USE db1; UPDATE db1.table1, db2.table2 SET db1.table1.col1 = 10, db2.table2.col2 = 20;如果使用基于语句的日志记录,两个表的更新都会被写入二进制日志。然而,当使用基于行的格式时,只有
table1的更改被记录;table2位于不同的数据库中,因此不会受到UPDATE的影响。现在假设,而不是使用USE db1语句,而是使用了USE db4语句:USE db4; UPDATE db1.table1, db2.table2 SET db1.table1.col1 = 10, db2.table2.col2 = 20;当使用基于语句的日志记录时,使用
UPDATE语句时不会被写入二进制日志。然而,当使用基于行的日志记录时,table1的更改被记录,但table2的更改不会被记录——换句话说,只有在由--binlog-do-db指定的数据库中的表的更改才会被记录,并且默认数据库的选择对此行为没有影响。 -
--binlog-ignore-db=*db_name*命令行格式 --binlog-ignore-db=name类型 字符串 这个选项对二进制日志记录的影响类似于
--replicate-ignore-db对复制的影响。此选项的效果取决于是否使用基于语句或基于行的日志记录格式,就像
--replicate-ignore-db的效果取决于是否使用基于语句或基于行的复制一样。您应该记住,用于记录给定语句的格式可能不一定与binlog_format的值所指示的格式相同。例如,DDL 语句(如CREATE TABLE和ALTER TABLE)始终作为语句记录,而不考虑生效的日志记录格式,因此对于--binlog-ignore-db的以下基于语句的规则始终适用于确定该语句是否被记录。基于语句的日志记录。 告诉服务器不记录默认数据库(即由
USE选择的数据库)为*db_name*的任何语句。当没有默认数据库时,不会应用
--binlog-ignore-db选项,并且这些语句始终被记录。 (Bug #11829838, Bug #60188)基于行的格式。 告诉服务器不要记录对数据库*
db_name*中任何表的更新。当前数据库不起作用。在使用基于语句的日志记录时,以下示例不会按您期望的方式工作。假设服务器是使用
--binlog-ignore-db=sales启动的,并且您发出以下语句:USE prices; UPDATE sales.january SET amount=amount+1000;在这种情况下,
UPDATE语句会被记录,因为--binlog-ignore-db仅适用于默认数据库(由USE语句确定)。由于sales数据库在语句中明确指定,因此该语句未被过滤。但是,在使用基于行的日志记录时,UPDATE语句的效果不会写入二进制日志,这意味着sales.january表的任何更改都不会被记录;在这种情况下,--binlog-ignore-db=sales导致忽略对源数据库副本中sales数据库中表所做的所有更改以进行二进制日志记录。要忽略多个数据库,请多次使用此选项,每个数据库使用一次。因为数据库名称可以包含逗号,如果提供逗号分隔的列表,则该列表将被视为单个数据库的名称。
如果您正在使用跨数据库更新并且不希望将这些更新记录下来,则不应使用此选项。
校验和选项。 MySQL 支持读取和写入二进制日志校验和。可以使用以下两个选项启用它们:
-
--binlog-checksum={NONE|CRC32}命令行格式 --binlog-checksum=type类型 字符串 默认值 CRC32有效值 NONE``CRC32启用此选项会导致源代码为写入二进制日志的事件生成校验和。设置为
NONE以禁用,或者设置要用于生成校验和的算法的名称;目前仅支持 CRC32 校验和,CRC32 是默认值。您不能在事务内更改此选项的设置。
要控制副本(从中继日志)读取校验和,请使用--slave-sql-verify-checksum选项。
测试和调试选项。 以下二进制日志选项用于复制测试和调试。它们不适用于正常操作。
-
--max-binlog-dump-events=*N*命令行格式 --max-binlog-dump-events=#类型 整数 默认值 0此选项仅在 MySQL 测试套件内部用于复制测试和调试。
-
--sporadic-binlog-dump-fail命令行格式 --sporadic-binlog-dump-fail[={OFF|ON}]类型 布尔 默认值 OFF此选项仅在 MySQL 测试套件内部用于复制测试和调试。
与二进制日志一起使用的系统变量
以下列表描述了用于控制二进制日志记录的系统变量。它们可以在服务器启动时设置,并且其中一些可以使用 SET 在运行时更改。用于控制二进制日志记录的服务器选项在本节的前面列出。
-
binlog_cache_size命令行格式 --binlog-cache-size=#系统变量 binlog_cache_size范围 全局 动态 是 SET_VAR提示适用否 类型 整数 默认值 32768最小值 4096最大值(64 位平台) 18446744073709547520最大值(32 位平台) 4294963200单位 字节 块大小 4096在事务期间保存对二进制日志的更改的内存缓冲区的大小。
当服务器启用二进制日志记录(使用
log_bin系统变量设置为 ON)时,如果服务器支持任何事务性存储引擎,则为每个客户端分配一个二进制日志缓存。如果事务的数据超过内存缓冲区的空间,多余的数据将存储在临时文件中。当服务器上启用二进制日志加密时,内存缓冲区不加密,但(从 MySQL 8.0.17 开始)用于保存二进制日志缓存的任何临时文件是加密的。在每个事务提交后,通过清除内存缓冲区并截断使用的临时文件来重置二进���日志缓存。如果经常使用大型事务,可以增加此缓存大小以获得更好的性能,从而减少或消除写入临时文件的需求。
Binlog_cache_use和Binlog_cache_disk_use状态变量可用于调整此变量的大小。参见 第 7.4.4 节,“二进制日志”。binlog_cache_size仅设置事务缓存的大小;语句缓存的大小由binlog_stmt_cache_size系统变量控制。 -
binlog_checksum命令行格式 --binlog-checksum=type系统变量 binlog_checksum范围 全局 动态 是 SET_VAR提示适用否 类型 字符串 默认值 CRC32有效值 NONE``CRC32启用此变量会导致源为二进制日志中的每个事件编写校验和。
binlog_checksum支持值NONE(禁用校验和)和CRC32。默认值为CRC32。当禁用binlog_checksum(值为NONE)时,服务器通过为每个事件编写和检查事件长度(而不是校验和)来验证仅将完整事件写入二进制日志。在源上将此变量设置为副本不识别的值会导致副本将其自己的
binlog_checksum值设置为NONE,并因错误而停止复制。如果与旧副本的向后兼容性是一个问题,您可能希望将值明确设置为NONE。直到 MySQL 8.0.20,Group Replication 无法使用校验和,也不支持二进制日志中的校验和,因此在配置服务器实例成为组成员时,必须设置
binlog_checksum=NONE。从 MySQL 8.0.21 开始,Group Replication 支持校验和,因此组成员可以使用默认设置。更改
binlog_checksum的值会导致二进制日志被旋转,因为必须为整个二进制日志文件编写校验和,而不能仅为部分文件编写。您不能在事务内更改binlog_checksum的值。当使用
binlog_transaction_compression系统变量启用二进制日志事务压缩时,不会为压缩的事务负载中的每个事件编写校验和。相反,为 GTID 事件编写校验和,并为压缩的Transaction_payload_event编写校验和。 -
binlog_direct_non_transactional_updates命令行格式 --binlog-direct-non-transactional-updates[={OFF|ON}]系统变量 binlog_direct_non_transactional_updates范围 全局,会话 动态 是 SET_VAR提示适用否 类型 布尔值 默认值 OFF由于并发问题,当事务包含对事务表和非事务表的更新时,复制品可能会变得不一致。MySQL 试图通过将非事务语句写入事务缓存来保留这些语句之间的因果关系,该缓存在提交时被刷新。然而,当代表事务对非事务表进行的修改立即对其他连接可见时,问题就会出现,因为这些更改可能不会立即���入二进制日志。
binlog_direct_non_transactional_updates变量提供了解决此问题的一种可能方法。默认情况下,此变量已禁用。启用binlog_direct_non_transactional_updates会导致对非事务表的更新直接写入二进制日志,而不是写入事务缓存。截至 MySQL 8.0.14 版本,设置此系统变量的会话值是一项受限操作。会话用户必须具有足够权限来设置受限会话变量。请参阅第 7.1.9.1 节,“系统变量权限”。
binlog_direct_non_transactional_updates仅适用于使用基于语句的二进制日志格式复制的语句;也就是说,仅当binlog_format的值为STATEMENT时,或者当binlog_format为MIXED且给定语句正在使用基于语句的格式进行复制时才起作用。当二进制日志格式为ROW时,或者当binlog_format设置为MIXED且给定语句使用基于行的格式进行复制时,此变量不起作用。重要提示
在启用此变量之前,您必须确保事务表和非事务表之间没有依赖关系;这种依赖关系的一个示例是语句
INSERT INTO myisam_table SELECT * FROM innodb_table。否则,这些语句很可能会导致复制品与源之间出现分歧。当二进制日志格式为
ROW或MIXED时,此变量不起作用。 -
binlog_encryption命令行格式 --binlog-encryption[={OFF|ON}]引入版本 8.0.14 系统变量 binlog_encryption作用范围 全局 动态 是 SET_VAR提示适用否 类型 布尔值 默认值 OFF启用此服务器上二进制日志文件和中继日志文件的加密。
OFF是默认设置。ON设置二进制日志文件和中继日志文件的加密。不需要在服务器上启用二进制日志记录以启用加密,因此可以在没有二进制日志的副本上加密中继日志文件。要使用加密,必须安装并配置一个密钥环插件以提供 MySQL 服务器的密钥环服务。有关如何执行此操作的说明,请参见第 8.4.4 节,“MySQL 密钥环”。任何受支持的密钥环插件都可以用于存储二进制日志加密密钥。当首次启用二进制日志加密启动服务器时,在初始化二进制日志和中继日志之前会生成一个新的二进制日志加密密钥。此密钥用于为每个二进制日志文件(如果服务器启用了二进制日志记录)和中继日志文件(如果服务器有复制通道)加密一个文件密码,并且从文件密码生成的进一步密钥用于加密文件中的数据。中继日志文件为所有通道加密,包括组复制应用程序通道和在激活加密后创建的新通道。二进制日志索引文件和中继日志索引文件永远不会被加密。
如果在服务器运行时激活加密,那么此时会生成一个新的二进制日志加密密钥。例外情况是,如果以前在服务器上激活了加密,然后禁用了,那么之前使用的二进制日志加密密钥将再次被使用。二进制日志文件和中继日志文件立即进行轮换,并且新文件和所有后续二进制日志文件和中继日志文件的文件密码都使用此二进制日志加密密钥进行加密。仍然存在于服务器上的现有二进制日志文件和中继日志文件不会自动加密,但如果不再需要,可以将它们清除。
如果通过将
binlog_encryption系统变量更改为OFF来停用加密,则二进制日志文件和中继日志文件将立即进行轮换,并且所有后续记录都将是未加密的。以前加密的文件不会自动解密,但服务器仍然能够读取它们。激活或停用加密时需要BINLOG_ENCRYPTION_ADMIN权限(或已弃用的SUPER权限)。组复制应用程序通道不包括在中继日志轮换请求中,因此在正常使用中,这些通道的未加密记录直到它们的日志轮换后才开始。有关二进制日志文件和中继日志文件加密的更多信息,请参见第 19.3.2 节,“加密二进制日志文件和中继日志文件”。
-
binlog_error_action命令行格式 --binlog-error-action[=value]系统变量 binlog_error_action范围 全局 动态 是 SET_VAR提示适用否 类型 枚举 默认值 ABORT_SERVER有效值 IGNORE_ERROR``ABORT_SERVER控制服务器遇到无法写入、刷新或同步二进制日志等错误时会发生什么,这可能导致源二进制日志不一致,副本失去同步。
此变量默认为
ABORT_SERVER,当二进制日志遇到此类错误时,服务器会停止记录并关闭。在重新启动时,恢复的过程与意外服务器停止的情况相同(参见第 19.4.2 节,“处理复制的意外停止”)。当
binlog_error_action设置为IGNORE_ERROR时,如果服务器遇到此类错误,它会继续进行当前事务,记录错误然后停止记录,并继续执行更新。要恢复二进制日志记录,必须重新启用log_bin,这需要重新启动服务器。此设置与 MySQL 的旧版本向后兼容。 -
binlog_expire_logs_seconds命令行格式 --binlog-expire-logs-seconds=#系统变量 binlog_expire_logs_seconds范围 全局 动态 是 SET_VAR提示适用否 类型 整数 默认值 2592000最小值 0最大值 4294967295单位 秒 设置二进制日志过期时间(以秒为单位)。在过期后,二进制日志文件可以自动删除。可能的删除发生在启动时和二进制日志刷新时。日志刷新的发生如第 7.4 节,“MySQL 服务器日志”所示。
默认的二进制日志过期时间为 2592000 秒,相当于 30 天(302460*60 秒)。如果在启动时既没有为
binlog_expire_logs_seconds设置值,也没有为废弃的系统变量expire_logs_days设置值,则使用默认值。如果在启动时为binlog_expire_logs_seconds或expire_logs_days中的一个变量设置了非零值,则该值将用作二进制日志的过期时间。如果在启动时为这两个变量都设置了非零值,则binlog_expire_logs_seconds的值将用作二进制日志的过期时间,而expire_logs_days的值将被忽略并显示警告消息。在运行时,如果另一个变量
binlog_expire_logs_seconds或expire_logs_days当前已设置为非零值,则不能将binlog_expire_logs_seconds或expire_logs_days设置为非零值。由于binlog_expire_logs_seconds的默认值为非零,因此必须在设置或更改expire_logs_days的值之前明确将binlog_expire_logs_seconds设置为零。从 MySQL 8.0.29 开始,可以通过将系统变量
binlog_expire_logs_auto_purge设置为OFF来禁用二进制日志的自动清理。这优先于binlog_expire_logs_seconds的任何设置。在 MySQL 8.0.28 及更早版本中,要禁用二进制日志的自动清理,必须明确为
binlog_expire_logs_seconds指定值为 0,并且不为expire_logs_days指定值。为了与早期版本兼容,如果您明确为expire_logs_days指定值为 0,并且不为binlog_expire_logs_seconds指定值,则也会禁用自动清理。在这种情况下,不会应用binlog_expire_logs_seconds的默认值。要手动删除二进制日志文件,请使用
PURGE BINARY LOGS语句。参见 Section 15.4.1.1, “PURGE BINARY LOGS Statement”。 -
binlog_expire_logs_auto_purge命令行格式 --binlog-expire-logs-auto-purge={ON|OFF}引入版本 8.0.29 系统变量 binlog_expire_logs_auto_purge作用范围 全局 动态 是 SET_VAR提示适用否 类型 布尔值 默认值 ON启用或禁用二进制日志文件的自动清理。将此变量设置为
ON(默认值)启用自动清理;将其设置为OFF禁用自动清理。等待清理的间隔由binlog_expire_logs_seconds和expire_logs_days控制。注意
即使
binlog_expire_logs_auto_purge为ON,将binlog_expire_logs_seconds和expire_logs_days都设置为0也会阻止自动清理操作的进行。此变量对
PURGE BINARY LOGS没有影响。 -
binlog_format命令行格式 --binlog-format=format已弃用 8.0.34 系统变量 binlog_format范围 全局,会话 动态 是 SET_VAR提示适用否 类型 枚举 默认值 ROW有效值 MIXED``STATEMENT``ROW此系统变量设置了二进制日志记录格式,可以是
STATEMENT、ROW或MIXED中的任何一种。(参见第 19.2.1 节,“复制格式”。)当服务器启用二进制日志记录时,即log_bin系统变量设置为ON时,设置生效。在 MySQL 8.0 中,默认情况下启用二进制日志记录,并且默认使用基于行的格式。注意
binlog_format在 MySQL 8.0.34 中已被弃用,并可能在将来的 MySQL 版本中被移除。这意味着除基于行的日志记录格式外的其他格式的支持也可能在将来的版本中被移除。因此,任何新的 MySQL 复制设置应仅使用基于行的日志记录。binlog_format可以在启动时或运行时设置,但在某些情况下,在运行时更改此变量是不可能的,或会导致复制失败,如后文所述。默认值为
ROW。例外:在 NDB Cluster 中,默认值为MIXED;不支持基于语句的复制。设置此系统变量的会话值是受限制的操作。会话用户必须具有足够权限来设置受限制的会话变量。请参见第 7.1.9.1 节,“系统变量权限”。
更改此变量生效的规则和效果持续时间与其他 MySQL 服务器系统变量相同。有关更多信息,请参见第 15.7.6.1 节,“变量赋值的 SET 语法”。
当指定
MIXED时,将使用基于语句的复制,但有例外情况,即仅当仅有基于行的复制保证会产生正确结果时才会使用基于行的复制。例如,当语句包含可加载函数或UUID()函数时会发生这种情况。有关在设置每个二进制日志格式时如何处理存储程序(存储过程和函数、触发器和事件)的详细信息,请参见 Section 27.7,“存储程序二进制日志记录”。
在以下情况下无法在运行时切换复制格式:
-
无法从存储函数或触发器内部更改复制格式。
-
如果会话有打开的临时表,则无法为该会话更改复制格式(
SET @@SESSION.binlog_format)。 -
如果任何复制通道有打开的临时表,则无法全局更改复制格式(
SET @@GLOBAL.binlog_format或SET @@PERSIST.binlog_format)。 -
如果任何复制通道应用程序线程当前正在运行,则无法全局更改复制格式(
SET @@GLOBAL.binlog_format或SET @@PERSIST.binlog_format)。
在任何情况下尝试切换复制格式(或尝试设置当前复制格式)都会导致错误。但是,您可以随时使用
PERSIST_ONLY(SET @@PERSIST_ONLY.binlog_format)来更改复制格式,因为此操作不会修改运行时全局系统变量的值,并且只在服务器重新启动后生效。当存在任何临时表时不建议在运行时切换复制格式,因为仅在使用基于语句的复制时才记录临时表,而在基于行的复制和混合复制中,它们不会被记录���
在复制源服务器上更改日志格式不会导致副本更改其日志格式以匹配。在复制正在进行时切换复制格式可能会导致问题,如果副本启用了二进制日志记录,并且更改导致副本使用
STATEMENT格式记录日志,而源使用ROW或MIXED格式记录日志。副本无法将以ROW记录格式接收的二进制日志条目转换为STATEMENT格式以在自己的二进制日志中使用,因此此情况可能导致复制失败。有关更多信息,请参见 Section 7.4.4.2,“设置二进制日志格式”。二进制日志格式会影响以下服务器选项的行为:
-
--replicate-do-db -
--replicate-ignore-db -
--binlog-do-db -
--binlog-ignore-db
这些效果在���个选项的描述中有详细讨论。
-
-
binlog_group_commit_sync_delay命令行格式 --binlog-group-commit-sync-delay=#系统变量 binlog_group_commit_sync_delay范围 全局 动态 是 SET_VAR提示适用否 类型 整数 默认值 0最小值 0最大值 1000000单位 微秒 控制二进制日志提交在将二进制日志文件同步到磁盘之前等待多少微秒。默认情况下,
binlog_group_commit_sync_delay设置为 0,意味着没有延迟。将binlog_group_commit_sync_delay设置为微秒延迟可以使更多事务一起同步到磁盘,从而减少提交一组事务的总时间,因为较大的组需要更少的时间单位来完成。当设置
sync_binlog=0或sync_binlog=1时,binlog_group_commit_sync_delay指定的延迟将应用于每个二进制日志提交组在同步之前(或在sync_binlog=0的情况下,在继续之前)。当将sync_binlog设置为大于 1 的值n时,延迟将应用于每n个二进制日志提交组之后。设置
binlog_group_commit_sync_delay可以增加任何具有(或在故障转移后可能具有)副本的服务器上并因此可以增加副本的并行执行的提交事务数量。要从这种效果中受益,副本服务器必须设置replica_parallel_type=LOGICAL_CLOCK(从 MySQL 8.0.26 开始)或slave_parallel_type=LOGICAL_CLOCK,并且当binlog_transaction_dependency_tracking=COMMIT_ORDER也设置时效果更显著。在调整binlog_group_commit_sync_delay的设置时,重要的是考虑源的吞吐量和副本的吞吐量。设置
binlog_group_commit_sync_delay也可以减少在任何具有二进制日志的服务器(源或副本)上对二进制日志执行fsync()调用的次数。请注意,设置
binlog_group_commit_sync_delay会增加服务器上事务的延迟,可能会影响客户端应用程序。此外,在高并发工作负载下,延迟可能增加争用,从而降低吞吐量。通常,设置延迟的好处超过了缺点,但应始终进行调整以确定最佳设置。 -
binlog_group_commit_sync_no_delay_count命令行格式 --binlog-group-commit-sync-no-delay-count=#系统变量 binlog_group_commit_sync_no_delay_count范围 全局 动态 是 SET_VAR提示适用否 类型 整数 默认值 0最小值 0最大值 100000在由
binlog_group_commit_sync_delay指定的当前延迟中放弃之前等待的最大事务数。如果binlog_group_commit_sync_delay设置为 0,则此选项无效。 -
binlog_max_flush_queue_time命令行格式 --binlog-max-flush-queue-time=#已弃用 是 系统变量 binlog_max_flush_queue_time范围 全局 动态 是 SET_VAR提示适用否 类型 整数 默认值 0最小值 0最大值 100000单位 微秒 binlog_max_flush_queue_time已被弃用,并标记为在未来的 MySQL 版本中最终移除。以前,此系统变量控制了继续从刷新队列中读取事务的时间(以微秒为单位),然后进行组提交。它不再起作用。 -
binlog_order_commits命令行格式 --binlog-order-commits[={OFF|ON}]系统变量 binlog_order_commits范围 全局 动态 是 SET_VAR提示适用否 类型 布尔值 默认值 ON当在复制源服务器上启用此变量(默认情况下)时,发给存储引擎的事务提交指令在单个线程上串行化,因此事务总是按照写入二进制日志的顺序提交。禁用此变量允许使用多个线程发出事务提交指令。与二进制日志组提交结合使用,这可以防止单个事务的提交速率成为吞吐量的瓶颈,并可能产生性能改进。
事务在所有涉及的存储引擎确认事务准备提交时被写入二进制日志。然后二进制日志组提交逻辑在其写入二进制日志后提交一组事务。当禁用
binlog_order_commits时,由于使用多个线程进行此过程,提交组中的事务可能按照不同于二进制日志中的顺序提交。(来自单个客户端的事务总是按照时间顺序提交。)在许多情况下,这并不重要,因为在单独事务中执行的操作应该产生一致的结果,如果不是这种情况,则应该使用单个事务。如果您希望确保源端和多线程复制的事务历史保持一致,请在复制端设置
slave_preserve_commit_order=1。 -
binlog_rotate_encryption_master_key_at_startup命令行格式 --binlog-rotate-encryption-master-key-at-startup[={OFF|ON}]引入版本 8.0.14 系统变量 binlog_rotate_encryption_master_key_at_startup作用范围 全局 动态 否 SET_VARHint Applies否 类型 布尔值 默认值 OFF指定在服务器启动时是否会轮换二进制日志主密钥。二进制日志主密钥是用于加密服务器上的二进制日志文件和中继日志文件的文件密码的二进制日志加密密钥。当启用二进制日志加密(
binlog_encryption=ON)时,首次启动服务器时会生成一个新的二进制日志加密密钥,并用作二进制日志主密钥。如果binlog_rotate_encryption_master_key_at_startup系统变量也设置为ON,每当服务器重新启动时,会生成一个进一步的二进制日志加密密钥,并用作所有后续二进制日志文件和中继日志文件的二进制日志主密钥。如果binlog_rotate_encryption_master_key_at_startup系统变量设置为OFF,即默认情况下,服务器重新启动后会再次使用现有的二进制日志主密钥。有关二进制日志加密密钥和二进制日志主密钥的更多信息,请参见 Section 19.3.2, “Encrypting Binary Log Files and Relay Log Files”。 -
binlog_row_event_max_size命令行格式 --binlog-row-event-max-size=#系统变量 (≥ 8.0.14) binlog_row_event_max_size范围 (≥ 8.0.14) 全局 动态 (≥ 8.0.14) 否 SET_VAR提示适用 (≥ 8.0.14)否 类型 整数 默认值 8192最小值 256最大值 (64 位平台) 18446744073709551615最大值 (32 位平台) 4294967295单位 字节 当使用基于行的二进制日志记录时,此设置是行基二进制日志事件的最大大小的软限制,以字节为单位。在可能的情况下,存储在二进制日志中的行被分组为大小不超过此设置值的事件。如果无法拆分事件,则最大大小可能会超过。默认值为 8192 字节。
此全局系统变量是只读的,只能在服务器启动时设置。因此,其值只能通过在
SET语句中使用PERSIST_ONLY关键字或@@persist_only限定符来修改。 -
binlog_row_image命令行格式 --binlog-row-image=image_type系统变量 binlog_row_image范围 全局,会话 动态 是 SET_VAR提示适用否 类型 枚举 默认值 full有效值 full(记录所有列)minimal(仅记录更改的列和用于识别行的列)noblob(记录所有列,除了不需要的 BLOB 和 TEXT 列)对于 MySQL 基于行的复制,此变量确定如何将行图像写入二进制日志。
设置此系统变量的会话值是受限制的操作。会话用户必须具有足够权限来设置受限制的会话变量。请参阅 第 7.1.9.1 节,“系统变量权限”。
在 MySQL 基于行的复制中,每个行更改事件包含两个图像,一个“前”图像,其列与搜索要更新的行匹配,以及包含更改的“后”图像。通常,MySQL 记录完整行(即所有列)的前后图像。但是,并不严格要求在两个图像中都包含每一列,我们通常可以通过仅记录实际需要的列来节省磁盘、内存和网络使用。
注意
删除行时,仅记录前图像,因为删除后没有更改的值需要传播。插入行时,仅记录后图像,因为没有现有行需要匹配。仅在更新行时,才需要前后图像,并且两者都写入二进制日志。
对于前图像,只需要记录一组最小列,以唯一标识行。如果包含行的表具有主键,则只会将主键列写入二进制日志。否则,如果表具有所有列均为
NOT NULL的唯一键,则只需要记录唯一键中的列。 (如果表既没有主键也没有不带任何NULL列的唯一键,则必须在前图像中使用并记录所有列。)对于后图像,只需要记录实际更改的列。您可以使用
binlog_row_image系统变量使服务器记录完整或最小行。实际上,该变量可以取以下三个可能的值,如下列表所示:-
full:记录前图像和后图像中的所有列。 -
minimal:仅记录前图像中用于识别要更改的行的列;仅记录 SQL 语句指定的值或由自增生成的后图像中的列。 -
noblob:记录所有列(与full相同),但不记录不需要识别行或未更改的BLOB和TEXT列。
注意
NDB Cluster 不支持此变量;设置它不会影响对
NDB表的日志记录。默认值为
full。当使用
minimal或noblob时,仅当源表和目标表均满足以下条件时,删除和更新才能正确工作:-
所有列必须存在且顺序相同;每列必须使用与另一表中对应列相同的数据类型。
-
表必须具有相同的主键定义。
(换句话说,表必须相同,可能除了不是表主键的索引之外。)
如果不满足这些条件,则可能目标表中的主键列值不足以为删除或更新提供唯一匹配。在这种情况下,不会发出警告或错误;源表和副本会默默地发生分歧,从而破坏一致性。
当二进制日志格式为
STATEMENT时,设置此变量不起作用。当binlog_format为MIXED时,binlog_row_image的设置将应用于使用基于行格式记录的更改,但此设置对作为语句记录的更改没有影响。在全局或会话级别设置
binlog_row_image不会导致隐式提交;这意味着可以在事务进行中��改此变量而不影响事务。 -
-
binlog_row_metadata命令行格式 --binlog-row-metadata=metadata_type系统变量 binlog_row_metadata范围 全局 动态 是 SET_VAR提示适用否 类型 枚举 默认值 MINIMAL有效值 FULL(包括所有元数据)MINIMAL(限制包含的元数据)配置在使用基于行的日志记录时向二进制日志添加的表元数据的数量。当设置为
MINIMAL时,默认情况下,只记录与SIGNED标志、列字符集和几何类型相关的元数据。当设置为FULL时,将记录完整的表元数据,例如列名、ENUM或SET字符串值、PRIMARY KEY信息等。扩展元数据具有以下目的:
-
副本使用元数据在其表结构与源表不同的情况下传输数据。
-
外部软件可以使用元数据解码行事件并将数据存储到外部数据库,例如数据仓库。
-
-
binlog_row_value_options命令行格式 --binlog-row-value-options=#系统变量 binlog_row_value_options范围 全局,会话 动态 是 SET_VAR提示适用否 类型 设置 默认值 有效值 PARTIAL_JSON当设置为
PARTIAL_JSON时,这将启用一种节省空间的二进制日志格式,用于修改 JSON 文档中仅有小部分内容的更新,这会导致基于行的复制仅将 JSON 文档的修改部分写入二进制日志中的更新后图像,而不是写入完整文档(参见 JSON 值的部分更新)。这适用于使用任何JSON_SET()、JSON_REPLACE()和JSON_REMOVE()序列修改 JSON 列的UPDATE语句。如果服务器无法生成部分更新,则使用完整文档。默认值是一个空字符串,这会禁用该格式的使用。要取消
binlog_row_value_options并恢复写入完整 JSON 文档,将其值设置为空字符串。设置此系统变量的会话值是一项受限制的操作。会话用户必须具有足够权限来设置受限制的会话变量。请参阅第 7.1.9.1 节,“系统变量权限”。
binlog_row_value_options=PARTIAL_JSON仅在启用二进制日志记录且binlog_format设置为ROW或MIXED时生效。基于语句的复制始终仅记录 JSON 文档的修改部分,而不管为binlog_row_value_options设置了任何值。为了最大化节省的空间量,请与此选项一起使用binlog_row_image=NOBLOB或binlog_row_image=MINIMAL。binlog_row_image=FULL保存的空间比这两者少,因为完整的 JSON 文档存储在前图像中,而部分更新仅存储在后图像中。mysqlbinlog输出包括以使用
BINLOG语句编码为 base-64 字符串的事件形式的部分 JSON 更新。如果指定了--verbose选项,mysqlbinlog将以可读的 JSON 形式使用伪 SQL 语句显示部分 JSON 更新。MySQL 复制在副本上无法应用修改到 JSON 文档时会生成错误。这包括找不到路径的情况。请注意,即使有此类和其他安全检查,如果副本上的 JSON 文档与源上的不同,并且应用了部分更新,仍然存在在副本上生成有效但意外的 JSON 文档的理论可能性。
-
binlog_rows_query_log_events命令行格式 --binlog-rows-query-log-events[={OFF|ON}]系统变量 binlog_rows_query_log_events范围 全局,会话 动态 是 SET_VAR提示适用否 类型 布尔值 默认值 OFF此系统变量仅影响基于行的日志记录。启用时,会导致服务器将信息性日志事件(如行查询日志事件)写入其二进制日志中。此信息可用于调试和相关目的,例如在无法从行更新中重建时获取源上发出的原始查询。
设置此系统变量的会话值是受限制的操作。会话用户必须具有足够权限来设置受限制的会话变量。请参阅第 7.1.9.1 节,“系统变量权限”。
这些信息事件通常被 MySQL 程序忽略,读取二进制日志时不会引起任何问题,因此在复制或从备份中恢复时也不会有问题。要查看它们,请通过使用 mysqlbinlog 的
--verbose选项两次增加详细程度,可以是-vv或--verbose --verbose。 -
binlog_stmt_cache_size|命令行格式 --binlog-stmt-cache-size=#系统变量 binlog_stmt_cache_size范围 全局 动态 是 SET_VAR提示适用否 类型 整数 默认值 32768最小值 4096最大值(64 位平台) 18446744073709547520最大值(32 位平台) 4294963200单位 字节 块大小 4096用于二进制日志的内存缓冲区大小,用于保存在事务期间发出的非事务性语句。
当服务器上启用了二进制日志记录(使用
log_bin系统变量设置为 ON),如果服务器支持任何事务存储引擎,则为每个客户端分配单独的二进制日志事务和语句缓存。如果事务中使用的非事务性语句的数据超过内存缓冲区中的空间,则多余的数据将存储在临时文件中。当服务器上激活二进制日志加密时,内存缓冲区不加密,但(从 MySQL 8.0.17 开始)用于保存二进制日志缓存的任何临时文件是加密的。在每个事务提交后,通过清除内存缓冲区并截断使用的临时文件来重置二进制日志语句缓存。如果您在事务中经常使用大型非事务性语句,可以增加此缓存大小以通过减少或消除写入临时文件的需求来获得更好的性能。
Binlog_stmt_cache_use和Binlog_stmt_cache_disk_use状态变量可用于调整此变量的大小。请参阅第 7.4.4 节,“二进制日志”。binlog_cache_size系统变量设置事务缓存的大小。 -
binlog_transaction_compression命令行格式 --binlog-transaction-compression[={OFF|ON}]引入版本 8.0.20 系统变量 binlog_transaction_compression范围 全局,会话 动态 是 SET_VAR提示适用否 类型 布尔值 默认值 OFF启用对在此服务器上写入二进制日志文件的事务的压缩。
OFF是默认设置。使用binlog_transaction_compression_level_zstd系统变量设置用于压缩的 zstd 算法级别。启用二进制日志事务压缩后,事务负载将被压缩,然后作为单个事件(
Transaction_payload_event)写入二进制日志文件。压缩的事务负载在发送到副本、其他 Group Replication 组成员或诸如mysqlbinlog等客户端时仍保持压缩状态,并且在中继日志中仍以压缩状态写入。因此,二进制日志事务压缩既节省了事务发起者和接收者(以及它们的备份)的存储空间,又在服务器实例之间发送事务时节省了网络带宽。要使
binlog_transaction_compression=ON直接生效,必须在服务器上启用二进制日志记录。当 MySQL 服务器实例没有二进制日志时,如果它是从 MySQL 8.0.20 版本开始的,它可以接收、处理和显示压缩的事务负载,而不管其对binlog_transaction_compression的值如何。这些服务器实例接收的压缩事务负载以压缩状态写入中继日志,因此它们间接受益于复制拓扑中其他服务器执行的压缩。此系统变量在事务上下文中无法更改。设置此系统变量的会话值是受限操作。会话用户必须具有足够权限来设置受限会话变量。请参见第 7.1.9.1 节,“系统变量权限”。
有关二进制日志事务压缩的更多信息,包括哪些事件被压缩,哪些事件不被压缩,以及在使用事务压缩时行为的变化,请参见第 7.4.4.5 节,“二进制日志事务压缩”。
在 NDB 8.0.31 之前:在服务器运行时设置此变量对
NDB表的事务日志记录没有影响。可以通过在命令行或选项文件中启动 MySQL 时使用--binlog-transaction-compression=ON来为NDB表启用二进制日志事务压缩,但不能在服务器运行时启用或禁用。在 NDB 8.0.31 及更高版本中:您可以使用
ndb_log_transaction_compression系统变量来为NDB启用此功能。此外,在命令行或my.cnf文件中设置--binlog-transaction-compression=ON会导致在服务器启动时启用ndb_log_transaction_compression。有关该变量的详细信息,请参阅变量的描述。 -
binlog_transaction_compression_level_zstd命令行格式 --binlog-transaction-compression-level-zstd=#引入 8.0.20 系统变量 binlog_transaction_compression_level_zstd范围 全局,会话 动态 是 SET_VAR提示适用否 类型 整数 默认值 3最小值 1最大值 22设置此服务器上的二进制日志事务压缩级别,该功能由
binlog_transaction_compression系统变量启用。该值是一个整数,确定压缩工作量,从 1(最低工作量)到 22(最高工作量)。如果不指定此系统变量,则压缩级别设置为 3。随着压缩级别的增加,数据压缩比例增加,从而减少了事务负载所需的存储空间和网络带宽。然而,数据压缩所需的工作量也会增加,消耗源服务器上的时间、CPU 和内存资源。压缩工作量的增加与数据压缩比例的增加之间并没有线性关系。
此系统变量不能在事务上下文中更改。设置此系统变量的会话值是一项受限制的操作。会话用户必须具有足够权限来设置受限制的会话变量。请参阅第 7.1.9.1 节,“系统变量权限”。
此变量对
NDB表的事务日志记录没有影响;在 NDB Cluster 8.0.31 及更高版本中,您可以改用ndb_log_transaction_compression_level_zstd。 -
binlog_transaction_dependency_tracking命令行格式 --binlog-transaction-dependency-tracking=value已弃用 8.0.35 系统变量 binlog_transaction_dependency_tracking范围 全局 动态 是 SET_VAR提示适用否 类型 枚举 默认值 COMMIT_ORDER有效值 COMMIT_ORDER``WRITESET``WRITESET_SESSION对于具有多线程副本的复制源服务器(副本上的
replica_parallel_workers或slave_parallel_workers大于 0),binlog_transaction_dependency_tracking指定源mysqld生成的依赖信息的方式,该信息写入二进制日志以帮助副本确定哪些事务可以并行执行。复制源写入的依赖信息使用逻辑时间戳表示。(因此,设置此变量要求
replica_parallel_type或slave_parallel_type已设置为LOGICAL_CLOCK。)每个事务有两个逻辑时间戳,如下所示:-
sequence_number:对于给定二进制日志中的第一个事务,此值为 1,对于第二个事务为 2,依此类推。每个二进制日志文件中的编号重新从 1 开始。 -
last_committed:这指的是与当前事务发生冲突的最近提交事务的sequence_number。此值始终小于sequence_number。
binlog_transaction_dependency_tracking控制用于计算这些逻辑时间戳的方案的选择。可用选择如下:-
COMMIT_ORDER:如果第一个事务的提交时间窗口与第二个事务的提交时间窗口重叠,则认为两个事务是独立的。这是默认值。提交时间窗口从事务的最后一条语句执行后立即开始,并在存储引擎提交结束后立即结束。由于事务在这两个时间点之间持有所有行锁,我们知道它们不会更新相同的行。
-
WRITESET:逻辑时间戳基于COMMIT_ORDER与基于事务的写入集的第二方案的组合计算。事务中的每一行都向事务的写入集添加一个或多个哈希集,每个唯一键在行中都有一个。 (如果没有唯一的非空键,则使用行的哈希。)这包括已删除和已插入的行;对于更新的行,旧行和新行也包括在内。如果两个事务的写入集重叠,即两个事务的写入集中存在相同的某个数字(哈希),则认为这两个事务存在冲突。此外,由于写入集的计算方式,存在周期性的序列化点,使得写入集计算过程将序列化点之后的每个事务视为与序列化点之前的每个事务存在冲突。序列化点仅影响
WRITESET算法计算的依赖关系;序列化点两侧的事务可能具有重叠的提交时间窗口,因此尽管如此,在副本上可以并行化。DDL 语句、更新具有外键的表的事务以及会话值与全局值不同的transaction_write_set_extraction的事务会触发序列化点。如果自上一个序列化点以来提交的事务生成了至少binlog_transaction_dependency_history_size个唯一哈希,则还会强制执行序列化点。为了使多线程复制与 NDB 集群复制一起工作(NDB 8.0.33 及更高版本支持),源端必须将此变量设置为
WRITESET。有关更多信息,请参见第 25.7.11 节,“使用多线程应用程序的 NDB 集群复制”。 -
WRITESET_SESSION: 如果以下任一语句为真,则认为两个事务存在依赖关系:-
事务根据
WRITESET存在依赖关系。 -
事务在同一用户会话中提交。
-
在
WRITESET或WRITESET_SESSION模式下,源端使用COMMIT_ORDER为具有空或部分写入集的事务、更新没有主键或唯一键的表的事务以及更新外键关系中的父表的事务生成依赖信息。要将
binlog_transaction_dependency_tracking设置为WRITESET或WRITESET_SESSION,必须将transaction_write_set_extraction设置为OFF之外的值;默认值(XXHASH64)已足够。只要binlog_transaction_dependency_tracking的值为WRITESET或WRITESET_SESSION,就无法更改transaction_write_set_extraction。对于复制事务,任何值的更改在副本停止并使用STOP REPLICA和START REPLICA重新启动后才会生效。保留并检查最新事务更改给定行的行哈希数由
binlog_transaction_dependency_history_size的值确定。在从中继日志应用事务时,组复制在认证后执行自己的并行化,独立于为
binlog_transaction_dependency_tracking设置的任何值,但是该变量确实影响事务如何写入组复制成员的二进制日志。这些日志中的依赖信息用于协助从捐赠者的二进制日志进行状态传输的过程,该过程在成员加入或重新加入组时发生。对于该过程,将binlog_transaction_dependency_tracking设置为WRITESET可以根据组的工作负载提高组成员的性能。 -
-
binlog_transaction_dependency_history_size命令行格式 --binlog-transaction-dependency-history-size=#系统变量 binlog_transaction_dependency_history_size作用范围 全局 动态 是 SET_VARHint Applies否 类型 整数 默认值 25000最小值 1最大值 1000000设置在内存中保留并用于查找最后修改给定行的事务的行哈希数的上限。一旦达到这个哈希数,历史记录将被清除。
-
expire_logs_days命令行格式 --expire-logs-days=#已弃用 是 系统变量 expire_logs_days作用范围 全局 动态 是 SET_VARHint Applies否 类型 整数 默认值 0最小值 0最大值 99单位 天 指定自动删除二进制日志文件之前的天数。
expire_logs_days已弃用,您应该期望在将来的版本中将其删除。相反,请使用binlog_expire_logs_seconds,它以秒为单位设置二进制日志过期期限。如果您没有为任何系统变量设置值,则默认的过期期限为 30 天。可能的删除发生在启动时和二进制日志刷新时。如第 7.4 节,“MySQL 服务器日志”中所示,日志刷新发生。如果在启动时为
expire_logs_days指定了任何非零值,并且同时指定了binlog_expire_logs_seconds,则忽略该值,并使用binlog_expire_logs_seconds作为二进制日志过期期限。在这种情况下会发出警告消息。只有在未指定或指定为 0 时,启动时为expire_logs_days指定的非零值才会作为二进制日志过期期限。在运行时,如果另一个值已经被设置为非零值,你不能将
binlog_expire_logs_seconds或expire_logs_days设置为非零值。因为binlog_expire_logs_seconds的默认值为非零,所以你必须在设置或更改expire_logs_days的值之前,显式将binlog_expire_logs_seconds设置为零。要禁用二进制日志的自动清理,请明确为
binlog_expire_logs_seconds指定值为 0,并且不为expire_logs_days指定值。为了与早期版本兼容,如果明确为expire_logs_days指定值为 0,并且不为binlog_expire_logs_seconds指定值,则自动清理也会被禁用。在这种情况下,不会应用binlog_expire_logs_seconds的默认值。要手动删除二进制日志文件,请使用
PURGE BINARY LOGS语句。参见 Section 15.4.1.1, “PURGE BINARY LOGS 语句”。 -
log_bin系统变量 log_bin作用范围 全局 是否动态 否 SET_VAR提示适用否 类型 布尔值 显示服务器上二进制日志记录的状态,可以是启用(
ON)或禁用(OFF)。启用二进制日志记录后,服务器会记录所有更改数据的语句到二进制日志中,用于备份和复制。ON表示二进制日志可用,OFF表示未使用。可以使用--log-bin选项指定二进制日志的基本名称和位置。在早期的 MySQL 版本中,默认情况下禁用了二进制日志记录,只有在指定
--log-bin选项时才启用。从 MySQL 8.0 开始,默认情况下启用了二进制日志记录,无论是否指定了--log-bin选项,log_bin系统变量都设置为ON。唯一的例外是,如果您使用mysqld手动初始化数据目录,通过使用--initialize或--initialize-insecure选项,此时默认情况下禁用了二进制日志记录。在这种情况下,可以通过指定--log-bin选项来启用二进制日志记录。如果在启动时指定了
--skip-log-bin或--disable-log-bin选项,则禁用二进制日志记录,log_bin系统变量设置为OFF。如果同时指定了其中任何一个选项和--log-bin选项,则后面指定的选项优先。有关二进制日志的格式和管理信息,请参阅第 7.4.4 节,“二进制日志”。
-
log_bin_basename系统变量 log_bin_basename范围 全局 动态 否 SET_VAR提示适用否 类型 文件名 存储二进制日志文件的基本名称和路径,可以使用
--log-bin服务器选项进行设置。变量的最大长度为 256。在 MySQL 8.0 中,如果未提供--log-bin选项,则默认基本名称为binlog。为了与 MySQL 5.7 兼容,如果提供了--log-bin选项但没有字符串或为空字符串,则默认基本名称为*host_name*-bin,使用主机机器的名称。默认位置是数据目录。 -
log_bin_index命令行格式 --log-bin-index=file_name系统变量 log_bin_index范围 全局 动态 否 SET_VAR提示适用否 类型 文件名 保存二进制日志索引文件的基本名称和路径,可以使用
--log-bin-index服务器选项进行设置。变量长度最大为 256。 -
log_bin_trust_function_creators命令行格式 --log-bin-trust-function-creators[={OFF|ON}]已弃用 8.0.34 系统变量 log_bin_trust_function_creators范围 全局 动态 是 SET_VAR提示适用否 类型 布尔值 默认值 OFF此变量在启用二进制日志记录时应用。它控制存储函数创建者是否可信,不会创建可能导致不安全事件写入二进制日志的存储函数。如果设置为 0(默认值),除了具有
SUPER权限外,用户不允许创建或更改存储函数,还必须具有CREATE ROUTINE或ALTER ROUTINE权限。设置为 0 还强制要求函数必须声明具有DETERMINISTIC特性,或具有READS SQL DATA或NO SQL特性。如果将变量设置为 1,则 MySQL 不会强制执行这些限制以创建存储函数。此变量还适用于触发器创建。请参阅 第 27.7 节,“存储程序二进制日志记录”。 -
log_bin_use_v1_row_events命令行格式 --log-bin-use-v1-row-events[={OFF|ON}]已弃用 8.0.18 系统变量 log_bin_use_v1_row_events范围 全局 动态 是 SET_VAR提示适用否 类型 布尔值 默认值 OFF此只读系统变量已弃用。在服务器启动时将系统变量设置为
ON,通过使用 Version 1 二进制日志行事件而不是 MySQL 5.6 默认的 Version 2 二进制日志行事件,启用了与运行 MySQL Server 5.5 及更早版本的副本机器进行基于行的复制。 -
log_replica_updates命令行格式 --log-replica-updates[={OFF|ON}]引入 8.0.26 系统变量 log_replica_updates范围 全局 动态 否 SET_VAR提示适用否 类型 布尔值 默认值 ON从 MySQL 8.0.26 开始,使用
log_replica_updates替代从该版本开始弃用的log_slave_updates。在 MySQL 8.0.26 之前的版本中,请使用log_slave_updates。log_replica_updates指定了复制服务器从复制源服务器接收的更新是否应记录到复制服务器自己的二进制日志中。启用此变量会导致复制服务器将从源接收并由复制 SQL 线程执行的更新写入复制服务器自己的二进制日志中。二进制日志记录由
--log-bin选项控制,默认情况下启用,复制服务器上也必须启用二进制日志记录才能记录更新。请参阅第 19.1.6 节,“复制和二进制日志选项和变量”。log_replica_updates默认启用,除非您指定--skip-log-bin来禁用二进制日志记录,此时 MySQL 也会默认禁用复制更新记录。如果需要在启用二进制日志时禁用复制更新记录,请在复制服务器启动时指定--log-replica-updates=OFF。启用
log_replica_updates可以实现复制服务器的链式连接。例如,您可能希望使用以下安排设置复制服务器:A -> B -> C在这里,
A作为复制服务器B的源,B作为复制服务器C的源。为使此工作正常,B必须同时是源和复制服务器。启用二进制日志记录和log_replica_updates启用,这些是默认设置,从A接收的更新由B记录到其二进制日志中,因此可以传递给C。 -
log_slave_updates命令行格式 --log-slave-updates[={OFF|ON}]弃用 8.0.26 系统变量 log_slave_updates范围 全局 动态 否 SET_VAR提示适用否 类型 布尔值 默认值 ON从 MySQL 8.0.26 开始,
log_slave_updates已被弃用,应改用别名log_replica_updates。在 MySQL 8.0.26 之前的版本中,请使用log_slave_updates。log_slave_updates指定是否应将复制服务器从复制源服务器接收的更新记录到副本自己的二进制日志中。启用此变量会导致副本将从源接收并由复制 SQL 线程执行的更新写入副本自己的二进制日志中。必须还在副本上启用二进制日志记录,该记录由
--log-bin选项控制,并且默认情况下已启用,才能记录更新。请参阅第 19.1.6 节,“复制和二进制日志选项和变量”。默认情况下启用log_slave_updates,除非您指定--skip-log-bin来禁用二进制日志记录,此时 MySQL 也默认禁用副本更新记录。如果需要在启用二进制日志时禁用副本更新记录,请在副本服务器启动时指定--log-slave-updates=OFF。启用
log_slave_updates可以使复制服务器链接在一起。例如,您可能希望使用以下安排设置复制服务器:A -> B -> C在这里,
A作为副本B的源,B作为副本C的源。为了使其工作,B必须同时是源和副本。启用二进制日志记录和log_slave_updates启用,这些是默认设置,从A接收的更新由B记录到其二进制日志中,因此可以传递给C。 -
log_statements_unsafe_for_binlog命令行格式 --log-statements-unsafe-for-binlog[={OFF|ON}]弃用 8.0.34 系统变量 log_statements_unsafe_for_binlog范围 全局 动态 是 SET_VAR提示适用否 类型 布尔值 默认值 ON如果遇到错误 1592,控制生成的警告是否添加到错误日志中。
-
master_verify_checksum命令行格式 --master-verify-checksum[={OFF|ON}]已弃用 8.0.26 系统变量 master_verify_checksum作用范围 全局 动态 是 SET_VAR提示适用否 类型 布尔值 默认值 OFF从 MySQL 8.0.26 版本开始,
master_verify_checksum已被弃用,应改用别名source_verify_checksum。在 MySQL 8.0.26 版本之前的发布版本中,请使用master_verify_checksum。启用
master_verify_checksum会导致源通过检查校验和来验证从二进制日志中读取的事件,并在不匹配时停止并显示错误。master_verify_checksum默认情况下是禁用的;在这种情况下,源使用二进制日志中的事件长度来验证事件,因此只有完整的事件才会从二进制日志中读取。 -
max_binlog_cache_size命令行格式 --max-binlog-cache-size=#系统变量 max_binlog_cache_size作用范围 全局 动态 是 SET_VAR提示适用否 类型 整数 默认值(64 位平台) 18446744073709547520默认值(32 位平台) 4294967295最小值 4096最大值(64 位平台) 18446744073709547520最大值(32 位平台) 4294967295单位 字节 块大小 4096如果一个事务需要的字节数超过这个值,服务器会生成一个“多语句事务需要超过 'max_binlog_cache_size' 字节的存储空间”错误。当
gtid_mode不是ON时,最大推荐值为 4GB,因为在这种情况下,MySQL 无法处理大于 4GB 的二进制日志位置;当gtid_mode是ON时,这个限制不适用,服务器可以处理任意大小的二进制日志位置。如果由于
gtid_mode不是ON,或出于其他原因,您需要保证二进制日志不超过给定大小maxsize,则应根据此处显示的公式设置此变量:max_binlog_cache_size < (((*maxsize* - max_binlog_size) / max_connections) - 1000) / 1.2这个计算考虑了以下条件:
-
只要在开始写入之前的大小小于
max_binlog_size,服务器就会写入二进制日志。 -
服务器不会写入单个事务,而是一组事务。一组中可能的最大事务数等于
max_connections。 -
服务器会写入未包含在缓存中的数据。这包括每个事件的 4 字节校验和;虽然这只会增加不到事务大小的 20%,但这个量是不可忽略的。此外,服务器会为每个事务写入一个
Gtid_log_event;每个事件可能会使写入二进制日志的内容增加另外 1 KB。
max_binlog_cache_size仅设置事务缓存的大小;语句缓存的上限由max_binlog_stmt_cache_size系统变量控制。max_binlog_cache_size对会话的可见性与binlog_cache_size系统变量的可见性相匹配;换句话说,改变其值只会影响在值更改后启动的新会话。 -
-
max_binlog_size命令行格式 --max-binlog-size=#系统变量 max_binlog_size范围 全局 动态 是 SET_VAR提示适用否 类型 整数 默认值 1073741824最小值 4096最大值 1073741824单位 字节 块大小 4096如果写入二进制日志导致当前日志文件大小超过此变量的值,则服务器会旋转二进制日志(关闭当前文件并打开下一个文件)。最小值为 4096 字节。最大和默认值为 1GB。加密的二进制日志文件有额外的 512 字节头部,包含在
max_binlog_size中。事务被一次性写入二进制日志,因此永远不会在多个二进制日志之间分割。因此,如果你有大事务,你可能会看到比
max_binlog_size更大的二进制日志文件。如果
max_relay_log_size为 0,则max_binlog_size的值也适用于中继日志。在服务器上使用 GTIDs 时,当达到
max_binlog_size时,如果无法访问系统表mysql.gtid_executed以写入当前二进制日志文件中的 GTIDs,则无法旋转二进制日志。在这种情况下,服务器根据其binlog_error_action设置做出响应。如果设置为IGNORE_ERROR,服务器上会记录错误并停止二进制日志记录,或者如果设置为ABORT_SERVER,服务器将关闭。 -
max_binlog_stmt_cache_size命令行格式 --max-binlog-stmt-cache-size=#系统变量 max_binlog_stmt_cache_size范围 全局 动态 是 SET_VAR提示适用否 类型 整数 默认值 18446744073709547520最小值 4096最大值 18446744073709547520单位 字节 块大小 4096如果事务中的非事务性语句需要的内存超过这么多字节,服务器将生成错误。最小值为 4096。32 位平台上的最大和默认值为 4GB,在 64 位平台上为 16EB(艾字节)。
max_binlog_stmt_cache_size仅设置语句缓存的大小;事务缓存的上限完全由max_binlog_cache_size系统变量控制。 -
original_commit_timestamp系统变量 original_commit_timestamp范围 会话 动态 是 SET_VAR提示适用否 类型 数值 用于复制的内部使用。在副本上重新执行事务时,此值设置为事务在原始源上提交时的时间,以自纪元以来的微秒为单位。这允许原始提交时间戳在整个复制拓扑中传播。
设置此系统变量的会话值是受限操作。会话用户必须具有
REPLICATION_APPLIER权限(参见第 19.3.3 节,“复制权限检查”),或具有足够权限设置受限会话变量(参见第 7.1.9.1 节,“系统变量权限”)。但是,请注意,该变量不是供用户设置的;它是由复制基础设施自动设置的。 -
source_verify_checksum命令行格式 --source-verify-checksum[={OFF|ON}]引入版本 8.0.26 系统变量 source_verify_checksum作用域 全局 动态 是 SET_VAR提示适用否 类型 布尔值 默认值 OFF从 MySQL 8.0.26 开始,使用
source_verify_checksum代替从该版本开始已弃用的master_verify_checksum。在 MySQL 8.0.26 之前的版本中,请使用master_verify_checksum。启用
source_verify_checksum会导致源通过检查校验和来验证从二进制日志中读取的事件,并在不匹配时停止并显示错误。source_verify_checksum默认情况下是禁用的;在这种情况下,源使用二进制日志中的事件长度来验证事件,因此只有完整的事件才会从二进制日志中读取。 -
sql_log_bin系统变量 sql_log_bin作用域 会话 动态 是 SET_VAR提示适用否 类型 布尔值 默认值 ON此变量控制当前会话是否启用对二进制日志的记录(假设二进制日志本身已启用)。默认值为
ON。要为当前会话禁用或启用二进制日志记录,请将会话sql_log_bin变量设置为OFF或ON。将此变量设置为
OFF,以便在对源进行更改时暂时禁用二进制日志记录,这些更改不希望被复制到副本中。设置此系统变量的会话值是受限制的操作。会话用户必须具有足够权限来设置受限制的会话变量。请参阅第 7.1.9.1 节,“系统变量权限”。
不可能在事务或子查询中设置
sql_log_bin的会话值。将此变量设置为
OFF可防止将 GTID 分配给二进制日志中的事务。 如果您正在使用 GTID 进行复制,这意味着即使稍后重新启用二进制日志记录,从此时开始写入日志的 GTID 也不会考虑期间发生的任何事务,因此实际上这些事务会丢失。 -
sync_binlog命令行格式 --sync-binlog=#系统变量 sync_binlog作用范围 全局 动态 是 SET_VAR提示适用否 类型 整数 默认值 1最小值 0最大值 4294967295控制 MySQL 服务器将二进制日志同步到磁盘的频率。
-
sync_binlog=0:禁用 MySQL 服务器将二进制日志同步到磁盘。相反,MySQL 服务器依赖操作系统定期刷新二进制日志到磁盘,就像对任何其他文件一样。这个设置提供了最佳性能,但在断电或操作系统崩溃的情况下,可能会出现服务器已提交但尚未同步到二进制日志的事务。 -
sync_binlog=1:在提交事务之前将二进制日志同步到磁盘。这是最安全的设置,但由于增加了磁盘写入次数,可能会对性能产生负面影响。在断电或操作系统崩溃的情况下,二进制日志中缺失的事务仅处于准备状态。这允许自动恢复程序回滚事务,确保没有事务丢失在二进制日志中。 -
sync_binlog=*N*,其中N是除 0 或 1 之外的值:在收集了N个二进制日志提交组后,将二进制日志同步到磁盘。在断电或操作系统崩溃的情况下,可能会出现服务器已提交但尚未刷新到二进制日志的事务。这个设置可能会对性能产生负面影响,因为增加了磁盘写入次数。较高的值可以提高性能,但增加了数据丢失的风险。
对于使用
InnoDB和事务的复制设置,为了获得最大的耐久性和一致性,请使用以下设置:-
sync_binlog=1。 -
innodb_flush_log_at_trx_commit=1。
注意
许多操作系统和一些磁盘硬件会欺骗刷新到磁盘的操作。它们可能告诉mysqld刷新已经完成,即使实际上并没有。在这种情况下,即使使用推荐的设置,事务的耐久性也无法得到保证,最坏的情况下,停电可能会损坏
InnoDB数据。在 SCSI 磁盘控制器或磁盘本身中使用带电池后备的磁盘缓存可以加快文件刷新速度,并使操作更安全。您还可以尝试禁用硬件缓存中的磁盘写入缓存。 -
-
transaction_write_set_extraction命令行格式 --transaction-write-set-extraction[=value]已弃用 8.0.26 系统变量 transaction_write_set_extraction作用域 全局,会话 动态 是 SET_VAR提示适用否 类型 枚举 默认值 XXHASH64有效值 OFF``MURMUR32``XXHASH64此系统变量指定在事务期间提取的写入哈希的算法。默认值为
XXHASH64。OFF表示不收集写入集。transaction_write_set_extraction在 MySQL 8.0.26 中已弃用;预计将在未来的 MySQL 版本中删除。XXHASH64设置是 Group Replication 所必需的,用于从事务中提取写入以用于所有组成员的冲突检测和认证过程(参见 Section 20.3.1, “Group Replication Requirements”)。对于具有多线程副本的复制源服务器(在这些副本上,replica_parallel_workers或slave_parallel_workers设置为大于 0 的值),其中binlog_transaction_dependency_tracking设置为WRITESET或WRITESET_SESSION,transaction_write_set_extraction不能为OFF。当前binlog_transaction_dependency_tracking的值为WRITESET或WRITESET_SESSION时,不能更改transaction_write_set_extraction的值。截至 MySQL 8.0.14 版本,设置此系统变量的会话值是一项受限制的操作;会话用户必须具有足够的特权来设置受限制的会话变量(参见第 7.1.9.1 节,“系统变量特权”)。
binlog_format必须设置为ROW才能更改transaction_write_set_extraction的值。如果更改了该值,则新值在复制事务上不会立即生效,直到副本使用STOP REPLICA和START REPLICA停止并重新启动后才会生效。
原文:
dev.mysql.com/doc/refman/8.0/en/replication-options-gtids.html
19.1.6.5 全局事务 ID 系统变量
本节描述的 MySQL 服务器系统变量用于监视和控制全局事务标识符(GTIDs)。有关更多信息,请参见第 19.1.3 节,“具有全局事务标识符的复制”。
-
binlog_gtid_simple_recovery命令行格式 --binlog-gtid-simple-recovery[={OFF|ON}]系统变量 binlog_gtid_simple_recovery范围 全局 动态 否 SET_VAR提示��用否 类型 布尔值 默认值 ON此变量控制 MySQL 启动或重新启动时在搜索 GTID 时如何迭代二进制日志文件。
当
binlog_gtid_simple_recovery=TRUE(这是 MySQL 8.0 中的默认值)时,gtid_executed和gtid_purged的值在启动时基于最新和最旧的二进制日志文件中的Previous_gtids_log_event的值进行计算。有关计算的描述,请参见 gtid_purged 系统变量。此设置在服务器重新启动时仅访问两个二进制日志文件。如果服务器上的所有二进制日志都是使用 MySQL 5.7.8 或更高版本生成的,则始终可以安全地使用binlog_gtid_simple_recovery=TRUE。如果服务器上存在来自 MySQL 5.7.7 或更旧版本的任何二进制日志(例如,在将较旧服务器升级到 MySQL 8.0 后),并且使用
binlog_gtid_simple_recovery=TRUE,gtid_executed和gtid_purged可能会在以下两种情况下被错误初始化:-
最新的二进制日志是由 MySQL 5.7.5 或更早版本生成的,并且对于某些二进制日志,
gtid_mode为ON,但对于最新的二进制日志为OFF。 -
在 MySQL 5.7.7 或更早版本上发出了
SET @@GLOBAL.gtid_purged语句,并且在SET @@GLOBAL.gtid_purged语句时处于活动状态的二进制日志尚未被清除。
如果在任何情况下计算出了不正确的 GTID 集合,则即使稍后使用
binlog_gtid_simple_recovery=FALSE重新启动服务器,它仍然是不正确的。如果服务器存在任何这些情况或可能存在这些情况,请在启动或重新启动服务器之前设置binlog_gtid_simple_recovery=FALSE。当设置
binlog_gtid_simple_recovery=FALSE时,计算gtid_executed和gtid_purged的方法如 gtid_purged 系统变量中所述,将更改为按以下方式迭代二进制日志文件:-
不再使用最新的二进制日志文件中的
Previous_gtids_log_event和 GTID 日志事件的值,而是从最新的二进制日志文件开始计算gtid_executed,并使用从第一个二进制日志文件中找到的Previous_gtids_log_event值。如果服务器的最近的二进制日志文件没有 GTID 日志事件,例如如果服务器最初使用了gtid_mode=ON,但稍后将服务器更改为gtid_mode=OFF,这个过程可能需要很长时间。 -
不再使用最旧的二进制日志文件中的
Previous_gtids_log_event的值,而是从最旧的二进制日志文件开始计算gtid_purged,并使用从第一个二进制日志文件中找到的非空Previous_gtids_log_event值或至少一个 GTID 日志事件的值(表示从那一点开始使用 GTID)。如果服务器的旧二进制日志文件没有 GTID 日志事件,例如如果服务器最近才设置了gtid_mode=ON,这个过程可能需要很长时间。
-
-
enforce_gtid_consistency命令行格式 --enforce-gtid-consistency[=value]系统变量 enforce_gtid_consistency范围 全局 动态 是 SET_VAR提示适用否 类型 枚举 默认值 OFF有效值 OFF``ON``WARN根据此变量的值,服务器通过仅允许执行可以安全使用 GTID 记录的语句来强制执行 GTID 一致性。在启用基于 GTID 的复制之前,必须将此变量设置为
ON。enforce_gtid_consistency可配置的值为:-
OFF:允许所有事务违反 GTID 一致性。 -
ON:不允许任何事务违反 GTID 一致性。 -
WARN:允许所有事务违反 GTID 一致性,但在这种情况下会生成警告。
--enforce-gtid-consistency仅在对语句进行二进制日志记录时生效。如果服务器上禁用了二进制日志记录,或者如果语句未写入二进制日志因为它们被过滤器移除,那么对于未记录的语句,GTID 一致性不会被检查或强制执行。当
enforce_gtid_consistency设置为ON时,只有可以使用 GTID 安全语句记录的语句才能被记录,因此以下列出的操作不能与此选项一起使用:-
在事务中的
CREATE TEMPORARY TABLE或DROP TEMPORARY TABLE语句。 -
更新既包含事务表又包含非事务表的事务或语句。有一个例外,即如果所有非事务表都是临时表,则允许在同一事务或同一语句中使用非事务 DML。
-
CREATE TABLE ... SELECT语句,在 MySQL 8.0.21 之前。从 MySQL 8.0.21 开始,支持原子 DDL 的存储引擎允许CREATE TABLE ... SELECT语句。
更多信息,请参阅 Section 19.1.3.7, “使用 GTID 限制复制”。
在 MySQL 5.7 之前以及在该版本系列的早期版本中,布尔值
enforce_gtid_consistency默认为OFF。为了与这些早期版本保持兼容性,枚举默认为OFF,并且设置--enforce-gtid-consistency而不带值被解释为将值设置为ON。该变量还具有多个文本别名用于表示值:0=OFF=FALSE,1=ON=TRUE,2=WARN。这与其他枚举类型不同,但保持了与先前版本中使用的布尔类型的兼容性。这些更改影响了变量返回的内容。使用SELECT @@ENFORCE_GTID_CONSISTENCY,SHOW VARIABLES LIKE 'ENFORCE_GTID_CONSISTENCY'和SELECT * FROM INFORMATION_SCHEMA.VARIABLES WHERE 'VARIABLE_NAME' = 'ENFORCE_GTID_CONSISTENCY',都返回文本形式,而不是数字形式。这是一个不兼容的更改,因为@@ENFORCE_GTID_CONSISTENCY对于布尔值返回数字形式,但对于SHOW和信息模式返回文本形式。 -
-
gtid_executed系统变量 gtid_executed范围 全局 动态 否 SET_VARHint Applies否 类型 字符串 单位 GTID 集合 当与全局范围一起使用时,此变量包含服务器上执行的所有事务和由
SETgtid_purged语句设置的 GTIDs 的表示。这与SHOW MASTER STATUS和SHOW REPLICA STATUS输出中的Executed_Gtid_Set列的值相同。此变量的值是一个 GTID 集合,请参阅 GTID Sets 获取更多信息。当服务器启动时,
@@GLOBAL.gtid_executed被初始化。有关如何迭代二进制日志以填充gtid_executed的更多信息,请参阅binlog_gtid_simple_recovery。随着事务的执行或执行任何SETgtid_purged语句,GTIDs 将被添加到集合中。在任何给定时间可以在二进制日志中找到的事务集合等于
GTID_SUBTRACT(@@GLOBAL.gtid_executed, @@GLOBAL.gtid_purged);也就是说,所有尚未清除的二进制日志中的事务。执行
RESET MASTER会导致这个变量的全局值(但不包括会话值)被重置为空字符串。除非由于RESET MASTER而清除了该集合,否则 GTID 不会从该集合中删除。 -
gtid_executed_compression_period命令行格式 --gtid-executed-compression-period=#系统变量 gtid_executed_compression_period作用域 全局 动态 是 SET_VAR提示适用否 类型 整数 默认值(≥ 8.0.23) 0默认值(≤ 8.0.22) 1000最小值 0最大值 4294967295每处理这么多事务时,压缩
mysql.gtid_executed表。当服务器启用二进制日志记录时,不会使用这种压缩方法,而是在每次二进制日志轮换时压缩mysql.gtid_executed表。当服务器禁用二进制日志记录时,压缩线程会休眠,直到执行了指定数量的事务,然后唤醒以执行mysql.gtid_executed表的压缩。将此系统变量的值设置为 0 表示线程永远不会唤醒,因此不会使用这种显式压缩方法。相反,压缩会根据需要隐式发生。从 MySQL 8.0.17 开始,
InnoDB事务由一个单独的进程写入到mysql.gtid_executed表中,而非InnoDB事务。如果服务器同时存在InnoDB事务和非InnoDB事务,那么由这个系统变量控制的压缩会干扰这个进程的工作,并且可能显著减慢速度。因此,从那个版本开始,建议将gtid_executed_compression_period设置为 0。从 MySQL 8.0.23 开始,
InnoDB和非InnoDB事务由同一进程写入到mysql.gtid_executed表中,并且gtid_executed_compression_period的默认值为 0。更多信息请参见 mysql.gtid_executed 表压缩。
-
gtid_mode命令行格式 --gtid-mode=MODE系统变量 gtid_mode范围 全局 动态 是 SET_VAR提示适用否 类型 枚举 默认值 OFF有效值 OFF``OFF_PERMISSIVE``ON_PERMISSIVE``ON控制 GTID 基础日志记录是否启用以及日志可以包含什么类型的事务。您必须具有足够的权限来设置全局系统变量。请参阅第 7.1.9.1 节,“系统变量权限”。在设置
gtid_mode=ON之前,必须将enforce_gtid_consistency设置为ON。在修改此变量之前,请参阅第 19.1.4 节,“在线服务器上更改 GTID 模式”。记录的事务可以是匿名的或者使用 GTIDs。匿名事务依赖于二进制日志文件和位置来识别特定事务。GTID 事务具有用于引用事务的唯一标识符。不同的模式包括:
-
OFF: 新事务和复制事务都必须是匿名的。 -
OFF_PERMISSIVE: 新事务是匿名的。复制事务可以是匿名的或者 GTID 事务。 -
ON_PERMISSIVE: 新事务是 GTID 事务。复制事务可以是匿名的或���GTID 事务。 -
ON: 新事务和复制事务都必须是 GTID 事务。
从一个值更改为另一个值只能一次一步。例如,如果
gtid_mode当前设置为OFF_PERMISSIVE,则可以更改为OFF或ON_PERMISSIVE,但不能更改为ON。gtid_purged和gtid_executed的值是持久的,无论gtid_mode的值如何。因此,即使更改了gtid_mode的值,这些变量仍包含正确的值。 -
-
gtid_next系统变量 gtid_next范围 会话 动态 是 SET_VAR提示适用否 类型 枚举 默认值 AUTOMATIC有效值 AUTOMATIC``ANONYMOUS``<UUID>:<NUMBER>此变量用于指定下一个 GTID 是否以及如何获取。
设置此系统变量的会话值是受限制的操作。会话用户必须具有
REPLICATION_APPLIER权限(参见 Section 19.3.3, “Replication Privilege Checks”),或具有足够权限设置受限制的会话变量(参见 Section 7.1.9.1, “System Variable Privileges”)。gtid_next可以取以下任一值:-
AUTOMATIC: 使用下一个自动生成的全局事务 ID。 -
ANONYMOUS: 事务没有全局标识符,仅通过文件和位置进行标识。 -
以
UUID:NUMBER格式的全局事务 ID。
以上哪些选项有效取决于
gtid_mode的设置,更多信息请参见 Section 19.1.4.1, “Replication Mode Concepts”。如果gtid_mode为OFF,设置此变量不会产生任何效果。在将此变量设置为
UUID:NUMBER后,事务已经提交或回滚之后,必须再次发出明确的SET GTID_NEXT语句,然后才能执行其他语句。DROP TABLE或DROP TEMPORARY TABLE在将非临时表与临时表组合使用,或者使用事务存储引擎的临时表与使用非事务存储引擎的临时表时会失败,并显示明确的错误。 -
-
gtid_owned系统变量 gtid_owned范围 全局,会话 动态 否 SET_VAR提示适用否 类型 字符串 单元 GTID 集合 这个只读变量主要用于内部使用。其内容取决于其范围。
-
当在全局范围内使用时,
gtid_owned保存着服务器当前正在使用的所有 GTID 的列表,以及拥有它们的线程的 ID。这个变量主要用于多线程复制,以检查事务是否已经在另一个线程上应用。应用程序线程在处理事务时始终拥有事务的 GTID,因此@@global.gtid_owned在处理过程中显示 GTID 和所有者。当事务已经提交(或回滚)时,应用程序线程释放 GTID 的所有权。 -
当与会话范围一起使用时,
gtid_owned保存当前由此会话使用并拥有的单个 GTID。此变量主要用于测试和调试在客户端通过设置gtid_next显式分配事务的 GTID 时 GTID 的使用情况。在这种情况下,@@session.gtid_owned在客户端处理事务时始终显示 GTID,直到事务已提交(或回滚)。当客户端完成处理事务时,变量将被清除。如果会话使用gtid_next=AUTOMATIC,则gtid_owned仅在事务的提交语句执行期间短暂填充,因此无法从相关会话中观察到,尽管在正确时刻读取@@global.gtid_owned时会列出。如果您有跟踪客户端在会话中处理的 GTID 的要求,可以启用由session_track_gtids系统变量控制的会话状态跟踪器。
-
-
gtid_purged系统变量 gtid_purged范围 全局 动态 是 SET_VAR提示适用否 类型 字符串 单位 GTID 集合 全局值
gtid_purged系统变量(@@GLOBAL.gtid_purged)是一个 GTID 集,包含在服务器上已提交但不在服务器上任何二进制日志文件中存在的所有事务的 GTID。gtid_purged是gtid_executed的子集。gtid_purged中包含以下类别的 GTID:-
已在副本上以二进制日志记录禁用的事务的复制 GTID。
-
现在已清除的二进制日志文件中写入的事务的 GTID。
-
明确通过语句
SET @@GLOBAL.gtid_purged添加到集合中的 GTID。
当服务器启动时,全局的
gtid_purged的值会被初始化为一组 GTID。有关如何计算此 GTID 集合的信息,请参阅 gtid_purged 系统变量。如果服务器上存在来自 MySQL 5.7.7 或更早版本的二进制日志,则可能需要在服务器的配置文件中设置binlog_gtid_simple_recovery=FALSE以生成正确的计算。有关需要此设置的情况的详细信息,请参阅binlog_gtid_simple_recovery的描述。执行
RESET MASTER会导致gtid_purged的值被重置为空字符串。您可以设置
gtid_purged的值,以记录服务器上已应用某个 GTID 集合中的事务,尽管这些事务在服务器上的任何二进制日志中都不存在。此操作的一个示例用例是在服务器上恢复一个或多个数据库的备份时,但您没有包含这些事务的相关二进制日志。重要提示
GTID 仅在服务器实例上可用,直到有符号 64 位整数的非负值的数量(2 的 63 次方减 1)。如果您将
gtid_purged的值设置为接近此限制的数字,后续的提交可能会导致服务器耗尽 GTID 并执行binlog_error_action指定的操作。从 MySQL 8.0.23 开始,当服务器实例接近限制时会发出警告消息。从 MySQL 8.0 开始,有两种方法可以设置
gtid_purged的值。您可以用您指定的 GTID 集替换gtid_purged的值,或者将您指定的 GTID 集附加到已由gtid_purged持有的 GTID 集中。如果服务器没有现有的 GTIDs,例如您正在使用现有数据库的备份进行配置的空服务器,两种方法都会产生相同的结果。如果您正在恢复与服务器上已有的事务重叠的备份,例如用mysqldump(即使备份是部分的,也包括服务器上所有事务的 GTIDs)从源创建的部分转储替换受损表,使用第一种方法替换gtid_purged的值。如果您正在恢复与服务器上已有的事务不重叠的备份,例如使用来自两个不同服务器的转储进行多源复制的配置,使用第二种方法添加到gtid_purged的值。-
要用您指定的 GTID 集替换
gtid_purged的值,请使用以下语句:SET @@GLOBAL.gtid_purged = 'gtid_set'gtid_set必须是当前gtid_purged值的超集,并且不能与gtid_subtract(gtid_executed,gtid_purged)相交。换句话说,新的 GTID 集合必须包括已经在gtid_purged中的任何 GTIDs,并且不能包括尚未被清除的gtid_executed中的任何 GTIDs。gtid_set也不能包括任何在@@global.gtid_owned中的 GTIDs,即当前正在服务器上处理的事务的 GTIDs。结果是全局值
gtid_purged被设置为gtid_set,而gtid_executed的值变为gtid_set和先前gtid_executed的值的并集。 -
要将您指定的 GTID 集附加到
gtid_purged,请使用以下带有加号(+)的语句:SET @@GLOBAL.gtid_purged = '+gtid_set'gtid_set绝对不能与当前值gtid_executed相交。换句话说,新的 GTID 集不能包含gtid_executed中的任何 GTID,包括已经在gtid_purged中的事务。gtid_set也不能包含任何在@@global.gtid_owned中的 GTID,即当前正在服务器上处理的事务的 GTID。结果是
gtid_set被添加到gtid_executed和gtid_purged中。
-
注意
如果服务器上存在来自 MySQL 5.7.7 或更早版本的任何二进制日志(例如,在将旧服务器升级到 MySQL 8.0 后),在发出SET @@GLOBAL.gtid_purged语句后,您可能需要在重新启动服务器之前在服务器的配置文件中设置binlog_gtid_simple_recovery=FALSE,否则gtid_purged可能会计算错误。有关需要此设置的情况的详细信息,请参阅binlog_gtid_simple_recovery的描述。
19.1.7 常见的复制管理任务
原文:
dev.mysql.com/doc/refman/8.0/en/replication-administration.html
19.1.7.1 检查复制状态
19.1.7.2 在副本上暂停复制
19.1.7.3 跳过事务
一旦复制已经启动,它将在不需要太多常规管理的情况下执行。本节描述了如何检查复制状态,如何暂停副本,以及如何跳过副本上的失败事务。
提示
要部署多个 MySQL 实例,您可以使用 InnoDB 集群,它使您能够轻松管理一组 MySQL 服务器实例在 MySQL Shell 中。InnoDB 集群将 MySQL Group Replication 包装在一个编程环境中,使您能够轻松部署一组 MySQL 实例以实现高可用性。此外,InnoDB 集群与 MySQL Router 无缝接口,使您的应用程序可以连接到集群而无需编写自己的故障转移过程。然而,对于不需要高可用性的类似用例,您可以使用 InnoDB ReplicaSet。有关 MySQL Shell 的安装说明可以在这里找到。
原文:
dev.mysql.com/doc/refman/8.0/en/replication-administration-status.html
19.1.7.1 检查复制状态
管理复制过程时最常见的任务是确保复制正在进行,并且源端和副本之间没有错误发生。
您必须在每个副本上执行的SHOW REPLICA STATUS语句提供有关副本服务器和源服务器之间连接的配置和状态的信息。从 MySQL 8.0.22 开始,SHOW SLAVE STATUS已被弃用,可以使用SHOW REPLICA STATUS代替。性能模式具有提供此信息的复制表,以更易于访问的形式呈现。请参阅第 29.12.11 节,“性能模式复制表”。
在性能模式复制表中显示的复制心跳信息可以让您检查复制连接是否活动,即使源端最近没有向副本发送事件。如果二进制日志中的更新或未发送事件的时间超过心跳间隔时间,源端会向副本发送心跳信号。源端上的MASTER_HEARTBEAT_PERIOD设置(由CHANGE MASTER TO语句设置)指定了心跳的频率,默认为副本的连接超时时间的一半(由系统变量replica_net_timeout或slave_net_timeout指定)。性能模式表replication_connection_status显示了副本最近接收到心跳信号的时间,以及接收到的心跳信号数量。
如果您使用SHOW REPLICA STATUS语句来检查单个副本的状态,则该语句提供以下信息:
mysql> SHOW REPLICA STATUS\G
*************************** 1\. row ***************************
Replica_IO_State: Waiting for source to send event
Source_Host: 127.0.0.1
Source_User: root
Source_Port: 13000
Connect_Retry: 1
Source_Log_File: master-bin.000001
Read_Source_Log_Pos: 927
Relay_Log_File: slave-relay-bin.000002
Relay_Log_Pos: 1145
Relay_Source_Log_File: master-bin.000001
Replica_IO_Running: Yes
Replica_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Source_Log_Pos: 927
Relay_Log_Space: 1355
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Source_SSL_Allowed: No
Source_SSL_CA_File:
Source_SSL_CA_Path:
Source_SSL_Cert:
Source_SSL_Cipher:
Source_SSL_Key:
Seconds_Behind_Source: 0
Source_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Source_Server_Id: 1
Source_UUID: 73f86016-978b-11ee-ade5-8d2a2a562feb
Source_Info_File: mysql.slave_master_info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Replica_SQL_Running_State: Replica has read all relay log; waiting for more updates
Source_Retry_Count: 10
Source_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Source_SSL_Crl:
Source_SSL_Crlpath:
Retrieved_Gtid_Set: 73f86016-978b-11ee-ade5-8d2a2a562feb:1-3
Executed_Gtid_Set: 73f86016-978b-11ee-ade5-8d2a2a562feb:1-3
Auto_Position: 1
Replicate_Rewrite_DB:
Channel_Name:
Source_TLS_Version:
Source_public_key_path:
Get_Source_public_key: 0
Network_Namespace:
要检查状态报告中的关键字段,请查看:
-
Replica_IO_State:副本的当前状态。有关更多信息,请参阅第 10.14.5 节,“复制 I/O(接收器)线程状态” Thread States")和第 10.14.6 节,“复制 SQL 线程状态”。 -
Replica_IO_Running:用于读取源头二进制日志的 I/O(接收器)线程是否正在运行。通常情况下,你希望这个值为Yes,除非你尚未开始复制或已经使用STOP REPLICA明确停止了复制。 -
Replica_SQL_Running:用于执行中继日志中事件的 SQL 线程是否正在运行。与 I/O 线程一样,这通常应该是Yes。 -
Last_IO_Error、Last_SQL_Error:处理中继日志时 I/O(接收器)和 SQL(应用程序)线程注册的最后错误。理想情况下,这些应该为空,表示没有错误。 -
Seconds_Behind_Source:复制 SQL(应用程序)线程落后处理源头二进制日志的秒数。较高的数字(或递增的数字)可能表明复制无法及时处理源头的事件。Seconds_Behind_Source为 0 的值通常可以解释为复制已经追赶上源头,但也有一些情况并非严格如此。例如,如果源头和复制之间的网络连接中断,但复制 I/O(接收器)线程尚未注意到这一点;也就是说,replica_net_timeout或slave_net_timeout设置的时间段尚未过去。Seconds_Behind_Source的瞬时值可能无法准确反映当前情况。当复制 SQL(应用程序)线程已经追赶上 I/O 时,Seconds_Behind_Source显示为 0;但当复制 I/O(接收器)线程仍在排队新事件时,Seconds_Behind_Source可能会显示一个较大的值,直到复制应用程序线程执行完新事件。特别是在事件具有旧时间戳的情况下,如果在相对较短的时间内多次执行SHOW REPLICA STATUS,你可能会看到这个值在 0 和一个相对较大的值之间反复变化。
几对字段提供有关复制从源头二进制日志中读取事件并在中继日志中处理事件的进度信息:
-
(
Master_Log_file,Read_Master_Log_Pos):源头二进制日志中指示复制 I/O(接收器)线程已读取事件的坐标。 -
(
Relay_Master_Log_File,Exec_Master_Log_Pos):源头二进制日志中指示复制 SQL(应用程序)线程已执行从该日志接收的事件的坐标。 -
(
Relay_Log_File,Relay_Log_Pos):副本中继日志中的坐标,指示复制 SQL(应用程序)线程执行中继日志的进度。这些坐标对应于前面的坐标,但是以副本中继日志坐标表示,而不是源二进制日志坐标。
在源端,您可以使用SHOW PROCESSLIST检查连接的副本的状态,以查看正在运行的进程列表。副本连接在Command字段中具有Binlog Dump:
mysql> SHOW PROCESSLIST \G;
*************************** 4\. row ***************************
Id: 10
User: root
Host: replica1:58371
db: NULL
Command: Binlog Dump
Time: 777
State: Has sent all binlog to slave; waiting for binlog to be updated
Info: NULL
因为是副本驱动复制过程,所以在此报告中几乎没有可用的信息。
对于使用--report-host选项启动并连接到源端的副本,源端上的SHOW REPLICAS(或在 MySQL 8.0.22 之前,SHOW SLAVE HOSTS)语句显示有关副本的基本信息。输出包括副本服务器的 ID,--report-host选项的值,连接端口和源 ID:
mysql> SHOW REPLICAS;
+-----------+----------+------+-------------------+-----------+
| Server_id | Host | Port | Rpl_recovery_rank | Source_id |
+-----------+----------+------+-------------------+-----------+
| 10 | replica1 | 3306 | 0 | 1 |
+-----------+----------+------+-------------------+-----------+
1 row in set (0.00 sec)
原文:
dev.mysql.com/doc/refman/8.0/en/replication-administration-pausing.html
19.1.7.2 在副本上暂停复制
你可以使用STOP REPLICA和START REPLICA语句在副本上停止和启动复制。从 MySQL 8.0.22 开始,STOP SLAVE和START SLAVE已被弃用,可以使用STOP REPLICA和START REPLICA代替。
要停止源的二进制日志的处理,请使用STOP REPLICA:
mysql> STOP SLAVE;
Or from MySQL 8.0.22:
mysql> STOP REPLICA;
当复制停止时,复制 I/O(接收器)线程停止从源二进制日志读取事件并将其写入中继日志,SQL 线程停止从中继日志读取事件并执行它们。您可以通过指定线程类型单独暂停 I/O(接收器)或 SQL(应用程序)线程:
mysql> STOP SLAVE IO_THREAD;
mysql> STOP SLAVE SQL_THREAD;
Or from MySQL 8.0.22:
mysql> STOP REPLICA IO_THREAD;
mysql> STOP REPLICA SQL_THREAD;
要再次开始执行,请使用START REPLICA语句:
mysql> START SLAVE;
Or from MySQL 8.0.22:
mysql> START REPLICA;
要启动特定线程,请指定线程类型:
mysql> START SLAVE IO_THREAD;
mysql> START SLAVE SQL_THREAD;
Or from MySQL 8.0.22:
mysql> START REPLICA IO_THREAD;
mysql> START REPLICA SQL_THREAD;
对于仅通过处理来自源的事件来执行更新的副本,如果要执行备份或其他任务,则仅停止 SQL 线程可能很有用。I/O(接收器)线程继续从源读取事件,但不执行它们。这使得在重新启动 SQL(应用程序)线程时更容易让副本赶上。
仅停止接收线程使中继日志中的事件能够被应用程序线程执行,直到中继日志结束的地方。当您想要暂停执行以赶上已从源接收的事件,当您想要在副本上执行管理操作但又确保它已处理到特定点的所有更新时,这可能很有用。此方法还可用于在您对源进行管理操作时暂停副本上的事件接收。停止接收线程但允许应用程序线程运行有助于确保在再次启动复制时不会有大量待执行的事件积压。
原文:
dev.mysql.com/doc/refman/8.0/en/replication-administration-skip.html
19.1.7.3 跳过事务
如果由于复制事务中的事件问题而导致复制停止,则可以通过在副本上跳过失败的事务来恢复复制。在跳过事务之前,请确保复制 I/O(接收器)线程以及 SQL(应用程序)线程已停止。
首先,您需要确定导致错误的复制事件。错误的详细信息和最后成功应用的事务记录在性能模式表replication_applier_status_by_worker中。您可以使用mysqlbinlog检索和显示围绕错误发生时记录的事件。有关如何执行此操作的说明,请参阅第 9.5 节,“时间点(增量)恢复”。或者,您可以在副本上发出SHOW RELAYLOG EVENTS或在源上发出SHOW BINLOG EVENTS。
在跳过事务并重新启动副本之前,请检查以下几点:
-
停止复制的事务是否来自未知或不受信任的来源?如果是,请调查原因,以确定是否有任何安全考虑因素表明不应重新启动副本。
-
停止复制的事务是否需要在副本上应用?如果是,请进行适当的更正并重新应用该事务,或者在副本上手动协调数据。
-
停止复制的事务是否需要在源上应用?如果不需要,请在原始发生地的服务器上手动撤消该事务。
要跳过事务,请根据情况选择以下方法之一:
-
当使用 GTIDs 时(
gtid_mode为ON),请参阅第 19.1.7.3.1 节,“跳过带有 GTIDs 的事务”。 -
当不使用 GTIDs 或正在逐步引入 GTIDs 时(
gtid_mode为OFF、OFF_PERMISSIVE或ON_PERMISSIVE),请参阅第 19.1.7.3.2 节,“跳过不带 GTIDs 的事务”。 -
如果您已经使用
CHANGE REPLICATION SOURCE TO或CHANGE MASTER TO语句的ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS选项在复制通道上启用了 GTID 分配,请参阅第 19.1.7.3.2 节,“跳过没有 GTIDs 的事务”。在复制通道上使用ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS与为通道引入基于 GTID 的复制不同,您不能在这些通道上使用基于 GTID 的复制的事务跳过方法。
要在跳过事务后重新启动复制,请发出START REPLICA命令,如果副本是多源副本,则带有FOR CHANNEL子句。
19.1.7.3.1 跳过带有 GTIDs 的事务
当使用 GTIDs 时(gtid_mode为ON),即使事务内容被过滤掉,已提交事务的 GTID 也会在副本上持久化。这个特性可以防止副本在使用 GTID 自动定位重新连接到源时检索先前被过滤的事务。它还可以用于在副本上跳过一个事务,方法是提交一个空事务来代替失败的事务。
当您已经使用CHANGE REPLICATION SOURCE TO语句的ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS选项在复制通道上启用了 GTID 分配时,这种跳过事务的方法不适用。
如果失败的事务在工作线程中生成了错误,您可以直接从性能模式表replication_applier_status_by_worker中的APPLYING_TRANSACTION字段获取其 GTID。要查看该事务是什么,请在副本上发出SHOW RELAYLOG EVENTS或在源上发出SHOW BINLOG EVENTS,并搜索输出以找到由该 GTID 引导的事务。
当您已经评估了失败的事务是否需要采取其他适当的操作(如安全考虑)后,要跳过它,请在副本上提交一个与失败事务具有相同 GTID 的空事务。例如:
SET GTID_NEXT='aaa-bbb-ccc-ddd:N';
BEGIN;
COMMIT;
SET GTID_NEXT='AUTOMATIC';
在副本上存在这个空事务意味着当您发出START REPLICA语句重新启动复制时,副本将使用自动跳过功能来忽略失败的事务,因为它看到具有该 GTID 的事务已经被应用。如果副本是多源副本,则在提交空事务时不需要指定通道名称,但在发出START REPLICA时需要指定通道名称。
请注意,如果此副本正在使用二进制日志记录,则在将来该副本成为源或主时,空事务将进入复制流。如果您需要避免这种可能性,请考虑刷新和清除副本的二进制日志,就像这个例子一样:
FLUSH LOGS;
PURGE BINARY LOGS TO 'binlog.000146';
空事务的 GTID 是持久的,但事务本身通过清除二进制日志文件而被移除。
19.1.7.3.2 跳过没有 GTID 的事务
当 GTID 未被使用或正在逐步引入时(gtid_mode为OFF、OFF_PERMISSIVE或ON_PERMISSIVE),您可以通过发出SET GLOBAL sql_replica_skip_counter语句(从 MySQL 8.0.26 开始)或SET GLOBAL sql_slave_skip_counter语句来跳过指定数量的事件。或者,您可以通过发出CHANGE REPLICATION SOURCE TO或CHANGE MASTER TO语句来跳过一个或多个事件,以将源二进制日志位置向前移动。
当您在复制通道上使用ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS选项的CHANGE REPLICATION SOURCE TO或CHANGE MASTER TO语句启用 GTID 分配时,这些方法也是适用的。
当您使用这些方法时,重要的是要理解,您并不一定是跳过一个完整的事务,就像之前描述的基于 GTID 的方法总是这样。这些非 GTID 方法并不知道事务的存在,而是操作事件。二进制日志被组织为一系列称为事件组的组,每个事件组由一系列事件组成。
-
对于事务性表,一个事件组对应一个事务。
-
对于非事务性表,一个事件组对应一个单独的 SQL 语句。
一个单独的事务可以包含对事务性和非事务性表的更改。
当您使用SET GLOBAL sql_replica_skip_counter或SET GLOBAL sql_slave_skip_counter语句跳过事件,并且结果位置位于事件组的中间时,复制品会继续跳过事件,直到达到该组的末尾。然后执行将从下一个事件组开始。CHANGE REPLICATION SOURCE TO或CHANGE MASTER TO语句没有此功能,因此您必须小心确定重新启动复制的正确位置,即事件组的开头。但是,使用CHANGE REPLICATION SOURCE TO或CHANGE MASTER TO意味着您无需计算需要跳过的事件,就像使用SET GLOBAL sql_replica_skip_counter或SET GLOBAL sql_slave_skip_counter一样,而是可以直接指定重新启动的位置。
19.1.7.3.2.1 使用SET GLOBAL sql_slave_skip_counter跳过事务
当您已经评估了失败的事务以及之前描述的任何其他适当操作(如安全考虑)后,计算您需要跳过的事件数。一个事件通常对应于二进制日志中的一个 SQL 语句,但请注意,使用AUTO_INCREMENT或LAST_INSERT_ID()的语句在二进制日志中计为两个事件。当使用二进制日志事务压缩时,压缩的事务负载(Transaction_payload_event)被计为单个计数值,因此其中的所有事件都作为一个单元跳过。
如果您想跳过完整的事务,可以计算事件直到事务结束,或者只是跳过相关的事件组。请记住,使用SET GLOBAL sql_replica_skip_counter或SET GLOBAL sql_slave_skip_counter时,复制品会继续跳过到事件组的末尾。确保您不要跳得太远,进入下一个事件组或事务,以免也被跳过。
发出以下SET语句,其中*N*是要从源跳过的事件数:
SET GLOBAL sql_slave_skip_counter = *N*
Or from MySQL 8.0.26:
SET GLOBAL sql_replica_skip_counter = *N*
如果设置了gtid_mode=ON,或者复制 I/O(接收器)和 SQL(应用程序)线程正在运行,则无法发出此语句。
SET GLOBAL sql_replica_skip_counter 或 SET GLOBAL sql_slave_skip_counter 语句没有立即生效。当你在这个 SET 语句之后再次发出 START REPLICA 语句时,系统变量 sql_replica_skip_counter 或 sql_slave_skip_counter 的新值会生效,并且事件会被跳过。那个 START REPLICA 语句也会自动将系统变量的值设置回 0。如果复制品是多源复制品,则在发出那个 START REPLICA 语句时,FOR CHANNEL 子句是必需的。确保你命名了正确的通道,否则事件会在错误的通道上被跳过。
19.1.7.3.2.2 跳过事务使用 CHANGE MASTER TO
当你评估了失败的事务以及之前描述的任何其他适当操作(如安全考虑)后,确定源二进制日志中表示适当位置以重新启动复制的坐标(文件和位置)。这可以是导致问题的事件后的事件组的开始,或者下一个事务的开始。复制 I/O(接收器)线程在下次启动时从这些坐标开始读取源,跳过失败的事件。确保你准确地确定了位置,因为这个语句不考虑事件组。
发出以下 CHANGE REPLICATION SOURCE TO 或 CHANGE MASTER TO 语句,其中 source_log_name 是包含重新启动位置的二进制日志文件,source_log_pos 是表示二进制日志文件中重新启动位置的数字:
CHANGE MASTER TO MASTER_LOG_FILE='*source_log_name*', MASTER_LOG_POS=*source_log_pos*;
Or from MySQL 8.0.24:
CHANGE REPLICATION SOURCE TO SOURCE_LOG_FILE='*source_log_name*', SOURCE_LOG_POS=*source_log_pos*;
如果复制品是多源复制品,则必须在 CHANGE REPLICATION SOURCE TO 或 CHANGE MASTER TO 语句中使用 FOR CHANNEL 子句来命名适当的通道。
如果 SOURCE_AUTO_POSITION=1 或 MASTER_AUTO_POSITION=1 被设置,或者复制 I/O(接收器)和 SQL(应用程序)线程正在运行,则无法发出此语句。如果在通常设置为 SOURCE_AUTO_POSITION=1 或 MASTER_AUTO_POSITION=1 时需要使用此跳过事务的方法,你可以在发出语句时将设置更改为 SOURCE_AUTO_POSITION=0 或 MASTER_AUTO_POSITION=0,然后之后再将其改回。例如:
CHANGE MASTER TO MASTER_AUTO_POSITION=0, MASTER_LOG_FILE='binlog.000145', MASTER_LOG_POS=235;
CHANGE MASTER TO MASTER_AUTO_POSITION=1;
Or from MySQL 8.0.24:
CHANGE REPLICATION SOURCE TO SOURCE_AUTO_POSITION=0, SOURCE_LOG_FILE='binlog.000145', SOURCE_LOG_POS=235;
CHANGE REPLICATION SOURCE TO SOURCE_AUTO_POSITION=1;
19.2 复制实现
原文:
dev.mysql.com/doc/refman/8.0/en/replication-implementation.html
19.2.1 复制格式
19.2.2 复制通道
19.2.3 复制线程
19.2.4 中继日志和复制元数据存储库
19.2.5 服务器如何评估复制过滤规则
复制基于源服务器跟踪其数据库的所有更改(更新、删除等)在其二进制日志中。二进制日志充当自服务器启动以来修改数据库结构或内容(数据)的所有事件的书面记录。通常,SELECT语句不会被记录,因为它们既不修改数据库结构也不修改内容。
连接到源的每个副本都请求二进制日志的副本。也就是说,它从源拉取数据,而不是源推送数据到副本。副本还执行接收到的二进制日志中的事件。这样做的效果是重复原始更改,就像它们在源上做的那样。表被创建或其结构被修改,数据根据最初在源上进行的更改被插入、删除和更新。
每个副本都是独立的,从源二进制日志中的更改重放在连接到源的每个副本上都是独立的。此外,因为每个副本只通过从源请求来接收二进制日志的副本,所以副本能够以自己的速度读取和更新数据库的副本,并且可以随意启动和停止复制过程,而不会影响到源端或副本端更新到最新数据库状态的能力。
有关复制实现的具体信息,请参阅第 19.2.3 节“复制线程”。
源服务器和副本定期报告有关复制过程的状态,以便您可以监视它们。有关所有与复制相关状态的描述,请参阅第 10.14 节“检查服务器线程(进程)信息”。
源的二进制日志在处理之前会被写入到副本的本地中继日志中。副本还记录有关源的二进制日志和本地中继日志的当前位置的信息。请参阅第 19.2.4 节“中继日志和复制元数据存储库”。
数据库更改在副本上根据一组规则进行过滤,这些规则根据控制事件评估的各种配置选项和变量进行应用。有关这些规则如何应用的详细信息,请参见第 19.2.5 节,“服务器如何评估复制过滤规则”。
19.2.1 复制格式
19.2.1.1 基于语句和基于行的复制的优缺点
19.2.1.2 基于行的日志记录和复制的用法
19.2.1.3 二进制日志记录中安全和不安全语句的确定
复制工作是因为写入二进制日志的事件从源读取,然后在副本上处理。根据事件类型,事件以不同格式记录在二进制日志中。使用的不同复制格式对应于事件记录在源二进制日志中时使用的二进制日志格式。二进制日志格式和复制期间使用的术语之间的关联为:
-
当使用基于语句的二进制日志记录时,源将 SQL 语句写入二进制日志。将源复制到副本的复制通过在副本上执行 SQL 语句来完成。这称为基于语句的复制(可以缩写为 SBR),对应于 MySQL 基于语句的二进制日志记录格式。
-
当使用基于行的日志记录时,源将事件写入二进制日志,指示如何更改单个表行。将源复制到副本的复制通过复制表示更改的事件到副本的表行来完成。这称为基于行的复制(可以缩写为 RBR)。
基于行的日志记录是默认方法。
-
您还可以配置 MySQL 使用基于语句和基于行的混合日志记录,具体取决于要记录的更改哪种最合适。这称为混合格式日志记录。在使用混合格式日志记录时,默认使用基于语句的日志。根据某些语句以及使用的存储引擎,日志在特定情况下会自动切换为基于行。使用混合格式的复制称为混合基于复制或混合格式复制。有关更多信息,请参见第 7.4.4.3 节“混合二进制日志记录格式”。
NDB 集群。 MySQL NDB Cluster 8.0 中的默认二进制日志记录格式为MIXED。您应该注意,NDB Cluster 复制始终使用基于行的复制,并且NDB存储引擎与基于语句的复制不兼容。有关更多信息,请参见第 25.7.2 节“NDB Cluster 复制的一般要求”。
当使用MIXED格式时,二进制日志格式部分由正在使用的存储引擎和正在执行的语句确定。有关混合格式日志记录和支持不同日志格式的规则,请参见 Section 7.4.4.3, “Mixed Binary Logging Format”。
在运行中的 MySQL 服务器中,日志格式由设置binlog_format服务器系统变量来控制。这个变量可以在会话或全局范围内设置。关于新设置何时以及如何生效的规则与其他 MySQL 服务器系统变量相同。为当前会话设置变量仅持续到该会话结束,且对其他会话不可见。全局设置变量会影响在更改后连接的客户端,但不会影响任何当前的客户端会话,包括更改变量设置的会话。要使全局系统变量设置永久生效,以便在服务器重新启动时应用,必须在选项文件中设置它。更多信息,请参见 Section 15.7.6.1, “SET Syntax for Variable Assignment”。
有条件下,您无法在运行时更改二进制日志格式,或者这样做会导致复制失败。请参见 Section 7.4.4.2, “Setting The Binary Log Format”。
更改全局binlog_format值需要足够权限来设置全局系统变量。更改会话binlog_format值需要足够权限来设置受限制的会话系统变量。请参见 Section 7.1.9.1, “System Variable Privileges”。
注意
更改二进制日志格式(binlog_format系统变量)在 MySQL 8.0.34 版中已被弃用。在将来的 MySQL 版本中,您可以期待binlog_format被完全移除,并且基于行的格式成为 MySQL 使用的唯一日志格式。
基于语句和基于行的复制格式有不同的问题和限制。要比较它们的相对优势和劣势,请参见 Section 19.2.1.1, “Advantages and Disadvantages of Statement-Based and Row-Based Replication”。
使用基于语句的复制时,可能会遇到复制存储过程或触发器的问题。您可以通过改用基于行的复制来避免这些问题。有关更多信息,请参见第 27.7 节,“存储程序二进制日志记录”。
19.2.1.1 基于语句和基于行的复制的优缺点
每种二进制日志格式都有其优缺点。对于大多数用户来说,混合复制格式应该提供最佳的数据完整性和性能组合。然而,如果您想在执行某些任务时利用基于语句或基于行的复制格式的特定功能,您可以使用本节中提供的信息,该信息提供了它们相对优缺点的摘要,以确定哪种最适合您的需求。
-
基于语句的复制的优点
-
基于语句的复制的缺点
-
基于行的复制的优点
-
基于行的复制的缺点
基于语句的复制的优点
-
已验证的技术。
-
写入日志文件的数据较少。当更新或删除影响许多行时,这导致日志文件所需的存储空间大大减少。这也意味着可以更快地进行备份和恢复操作。
-
日志文件包含所有进行任何更改的语句,因此可以用于审计数据库。
基于语句的复制的缺点
-
不适用于基于语句的不安全语句。 并非所有修改数据的语句(例如
INSERTDELETE,UPDATE, 和REPLACE语句)都可以使用基于语句的复制进行复制。任何非确定性行为在使用基于语句的复制时很难复制。此类数据修改语言(DML)语句的示例包括以下内容:-
依赖于不确定性的可加载函数或存储程序的语句,因为这些函数或存储程序返回的值取决于除提供给它的参数之外的因素。 (然而,基于行的复制只是复制函数或存储程序返回的值,因此其对表行和数据的影响在源和副本上是相同的。)有关更多信息,请参见第 19.5.1.16 节,“调用特性的复制”。
-
使用
LIMIT子句而没有ORDER BY的DELETE和UPDATE语句是不确定的。参见 Section 19.5.1.18, “Replication and LIMIT”. -
锁定读取语句(
SELECT ... FOR UPDATE和SELECT ... FOR SHARE)使用NOWAIT或SKIP LOCKED选项。参见 Locking Read Concurrency with NOWAIT and SKIP LOCKED. -
确定性可加载函数必须在副本上应用。
-
使用以下任何函数的语句无法使用基于语句的复制正确复制:
-
LOAD_FILE() -
UUID(),UUID_SHORT() -
USER() -
FOUND_ROWS() -
SYSDATE()(除非源和副本都使用--sysdate-is-now选项启动) -
GET_LOCK() -
IS_FREE_LOCK() -
IS_USED_LOCK() -
MASTER_POS_WAIT() -
RAND() -
RELEASE_LOCK() -
SOURCE_POS_WAIT() -
SLEEP() -
VERSION()
然而,所有其他函数都可以使用基于语句的复制正确复制,包括
NOW()等等。更多信息,请参见 Section 19.5.1.14, “Replication and System Functions”.
-
无法使用基于语句的复制正确复制的语句将记录警告,如下所示:
[Warning] Statement is not safe to log in statement format.在这种情况下,客户端也会收到类似的警告。客户端可以使用
SHOW WARNINGS显示它。 -
-
INSERT ... SELECT需要比基于行的复制更多的行级锁。 -
UPDATE语句需要进行表扫描(因为WHERE子句中未使用索引),必须锁定比基于行的复制更多的行。 -
对于
InnoDB:使用AUTO_INCREMENT的INSERT语句会阻塞其他不冲突的INSERT语句。 -
对于复杂语句,必须在副本上评估和执行语句,然后更新或插入行。使用基于行的复制,副本只需修改受影响的行,而不执行完整语句。
-
如果在副本上评估时出现错误,特别是在执行复杂语句时,基于语句的复制可能会随着时间逐渐增加受影响行的错误边界。请参见第 19.5.1.29 节,“复制期间的副本错误”。
-
存储函数执行与调用语句相同的
NOW()值。但是,存储过程不是这样的。 -
确定性可加载函数必须应用于副本。
-
表定义在源和副本上必须(几乎)完全相同。有关更多信息,请参见第 19.5.1.9 节,“源和副本上具有不同表定义的复制”。
-
从 MySQL 8.0.22 开始,从 MySQL 授予表中读取数据(通过连接列表或子查询)但不修改它们的 DML 操作将作为非锁定读取执行,并因此不适用于基于语句的复制。有关更多信息,请参见授予表并发性。
行级复制的优势
-
所有更改都可以复制。这是最安全的复制形式。
注意
更新
mysql系统模式中的信息的语句,例如GRANT、REVOKE以及触发器、存储过程(包括存储过程)和视图的操作,都使用基于语句的复制复制到副本。对于诸如
CREATE TABLE ... SELECT之类的语句,从表定义生成CREATE语句,并使用基于语句的格式进行复制,而行插入则使用基于行的格式进行复制。 -
源上需要更少的行锁,从而实现更高的并发性,适用于以下类型的语句:
-
INSERT ... SELECT -
带有
AUTO_INCREMENT的INSERT语句 -
带有不使用键或不更改大部分检查行的
WHERE子句的UPDATE或DELETE语句。
-
-
在复制品上,对于任何
INSERT、UPDATE或DELETE语句,需要更少的行锁。
基于行的复制的缺点
-
RBR 可以生成更多必须记录的数据。要复制一个 DML 语句(例如
UPDATE或DELETE语句),基于语句的复制仅将语句写入二进制日志。相比之下,基于行的复制将每个更改的行写入二进制日志。如果语句更改了许多行,基于行的复制可能会向二进制日志写入大量数据;即使对语句进行了回滚也是如此。这还意味着制作和恢复备份可能需要更多时间。此外,为了写入数据,二进制日志的锁定时间更长,这可能会导致并发问题。使用binlog_row_image=minimal可以大大减少这种劣势。 -
生成大型
BLOB值的确定性可加载函数在基于行的复制中复制所需的时间比基于语句的复制长。这是因为记录了BLOB列值,而不是生成数据的语句。 -
在复制品上,您无法看到从源接收并执行的语句。但是,您可以使用mysqlbinlog和选项
--base64-output=DECODE-ROWS以及--verbose查看哪些数据发生了变化。或者,使用
binlog_rows_query_log_events变量,如果启用,则在使用-vv选项时,向mysqlbinlog输出中添加一个Rows_query事件与语句。 -
对于使用
MyISAM存储引擎的表,在将它们作为基于行的事件应用到二进制日志时,对于INSERT语句,复制品上需要更强的锁定,而不是将它们作为语句应用。这意味着在使用基于行的复制时,不支持对MyISAM表的并发插入。
译文:
dev.mysql.com/doc/refman/8.0/en/replication-rbr-usage.html
19.2.1.2 基于行的日志记录和复制的用法
MySQL 使用基于语句的日志记录(SBL)、基于行的日志记录(RBL)或混合格式日志。所使用的二进制日志类型会影响日志的大小和效率。因此,在基于行的复制(RBR)和基于语句的复制(SBR)之间的选择取决于您的应用程序和环境。本节描述了使用基于行格式日志时的已知问题,并描述了在复制中使用它的一些最佳实践。
欲了解更多信息,请参阅第 19.2.1 节,“复制格式”和第 19.2.1.1 节,“基于语句和基于行复制的优缺点”。
有关 NDB 集群复制特定问题的信息(依赖于基于行的复制),请参阅第 25.7.3 节,“NDB 集群复制中的已知问题”。
-
临时表的基于行日志记录。 如第 19.5.1.31 节,“复制和临时表”所述,当使用基于行格式或(从 MySQL 8.0.4 开始)混合格式时,临时表不会被复制。有关更多信息,请参阅第 19.2.1.1 节,“基于语句和基于行复制的优缺点”。
当使用基于行或混合格式时,临时表不会被复制,因为没有必要。此外,由于临时表只能从创建它们的线程中读取,即使使用基于语句的格式,复制它们也很少或几乎没有任何好处。
即使已创建临时表,您可以在运行时从基于语句切换到基于行的二进制日志格式。然而,在 MySQL 8.0 中,您无法在运行时从基于行或混合格式切换到基于语句的二进制日志格式,因为在先前模式中省略了任何
CREATE TEMPORARY TABLE语句。MySQL 服务器跟踪创建每个临时表时生效的日志记录模式。当给定的客户端会话结束时,服务器会为仍然存在且在使用基于语句的二进制日志记录时创建的每个临时表记录一个
DROP TEMPORARY TABLE IF EXISTS语句。如果在创建表时使用基于行或混合格式的二进制日志记录,则不会记录DROP TEMPORARY TABLE IF EXISTS语句。在 MySQL 8.0.4 和 5.7.25 之前的版本中,无论生效的日志记录模式如何,都会记录DROP TEMPORARY TABLE IF EXISTS语句。当使用
binlog_format=ROW时,涉及临时表的非事务性 DML 语句是允许的,只要语句影响的非事务性表都是临时表(Bug #14272672)。 -
RBL 和非事务性表的同步。 当影响到许多行时,更改集会被拆分为几个事件;当语句提交时,所有这些事件都将写入二进制日志。在副本上执行时,会对涉及的所有表进行表锁定,然后以批处理模式应用行。根据副本表的引擎使用情况,这可能有效也可能无效。
-
延迟和二进制日志大小。 RBL 将每行的更改写入二进制日志,因此其大小可能会迅速增加。这可能会显著增加使副本上的更改与源上的更改匹配所需的时间。您应该意识到这种延迟可能对您的应用程序产生影响。
-
读取二进制日志。 mysqlbinlog 使用
BINLOG语句在二进制日志中显示基于行的事件。该语句将事件显示为一个 base 64 编码的字符串,其含义不明显。当使用--base64-output=DECODE-ROWS和--verbose选项调用时,mysqlbinlog将二进制日志的内容格式化为人类可读的形式。当二进制日志事件以基于行的格式编写,并且您想要读取或从复制或数据库故障中恢复时,您可以使用此命令读取二进制日志的内容。有关更多信息,请参见 Section 6.6.9.2, “mysqlbinlog Row Event Display”。 -
二进制日志执行错误和副本执行模式。 使用
slave_exec_mode=IDEMPOTENT通常仅在 MySQL NDB Cluster 复制中有用,其中IDEMPOTENT是默认值。(参见第 25.7.10 节,“NDB Cluster Replication: 双向和循环复制”)。当系统变量replica_exec_mode或slave_exec_mode为IDEMPOTENT时,由于找不到原始行而无法应用来自 RBL 的更改不会触发错误或导致复制失败。这意味着可能不会在副本上应用更新,导致源和副本不再同步。当replica_exec_mode或slave_exec_mode为IDEMPOTENT时,延迟问题和在 RBR 中使用非事务表可能导致源和副本进一步分歧。有关replica_exec_mode和slave_exec_mode的更多信息,请参见第 7.1.8 节,“服务器系统变量”。对于其他情况,将
replica_exec_mode或slave_exec_mode设置为STRICT通常足够;这是除NDB之外的存储引擎的默认值。 -
基于服务器 ID 的过滤不受支持。 您可以通过在
CHANGE REPLICATION SOURCE TO语句(从 MySQL 8.0.23 开始)或CHANGE MASTER TO语句(MySQL 8.0.23 之前)中使用IGNORE_SERVER_IDS选项来基于服务器 ID 进行过滤。此选项适用于基于语句和基于行的日志格式,但在设置GTID_MODE=ON时已被弃用。另一种在某些副本中过滤更改的方法是使用包含关系@@server_id <> *id_value*子句的WHERE子句与UPDATE和DELETE语句。例如,WHERE @@server_id <> 1。但是,这在基于行的日志记录中无法正常工作。要使用server_id系统变量进行语句过滤,请使用基于语句的日志记录。 -
RBL、非事务表和停止的副本。 当使用基于行的日志记录时,如果在副本线程更新非事务表时停止副本服务器,副本数据库可能会达到不一致的状态。因此,建议您对使用基于行格式复制的所有表使用事务存储引擎,如
InnoDB。在关闭副本 MySQL 服务器之前使用STOP REPLICA或STOP REPLICA SQL_THREAD(在 MySQL 8.0.22 之前,使用STOP slave或STOP SLAVE SQL_THREAD)有助于防止问题发生,并且无论您使用的是哪种日志格式或存储引擎,都建议始终这样做。
译文:
dev.mysql.com/doc/refman/8.0/en/replication-rbr-safe-unsafe.html
19.2.1.3 二进制日志中安全和不安全语句的确定
在 MySQL 复制中,一个语句的“安全性”指的是该语句及其效果是否可以使用基于语句的格式正确复制。如果这对于该语句是正确的,我们将该语句称为安全的;否则,我们将其称为不安全的。
通常情况下,如果一个语句是确定性的,那么它就是安全的;如果不是,则是不安全的。然而,某些非确定性函数不被视为不安全(请参见非确定性函数不被视为不安全,本节后面的内容)。此外,使用浮点数数学函数结果的语句——这些函数是依赖于硬件的——总是被视为不安全(请参见第 19.5.1.12 节,“复制和浮点值”)。
安全和不安全语句的处理。 一个语句的处理方式取决于该语句是否被视为安全,并且与二进制日志格式有关(即,binlog_format的当前值)。
-
在使用基于行的日志记录时,对于安全和不安全的语句没有区别对待。
-
在使用混合格式日志记录时,被标记为不安全的语句将使用基于行的格式记录;被视为安全的语句将使用基于语句的格式记录。
-
在使用基于语句的日志记录时,被标记为不安全的语句会生成相应的警告。安全的语句会正常记录。
每个被标记为不安全的语句都会生成一个警告。如果在源端执行了大量这样的语句,这可能导致错误日志文件过大。为了防止这种情况发生,MySQL 有一个警告抑制机制。每当在任何 50 秒内生成的最近 50 个ER_BINLOG_UNSAFE_STATEMENT警告超过 50 次时,警告抑制就会被启用。一旦激活,这将导致这类警告不会被写入错误日志;相反,对于每 50 个这种类型的警告,错误日志中会写入一个注释最后一个警告在最近的*N*秒内重复了*S*次。只要最近的 50 个这样的警告在 50 秒内或更短的时间内发出,这将继续进行;一旦速率降低到低于此阈值,警告将再次正常记录。警告抑制对于决定基于语句的日志记录中语句的安全性,以及如何将警告发送给客户端没有影响。MySQL 客户端仍然会为每个这样的语句接收一个警告。
更多信息,请参见 Section 19.2.1, “Replication Formats”。
被视为不安全的语句。 具有以下特征的语句被视为不安全:
-
包含可能在副本上返回不同值的系统函数的语句。 这些函数包括
FOUND_ROWS(),GET_LOCK(),IS_FREE_LOCK(),IS_USED_LOCK(),LOAD_FILE(),MASTER_POS_WAIT(),RAND(),RELEASE_LOCK(),ROW_COUNT(),SESSION_USER(),SLEEP(),SOURCE_POS_WAIT(),SYSDATE(),SYSTEM_USER(),USER(),UUID(), 和UUID_SHORT()。非确定性函数不被视为不安全。 尽管这些函数不是确定性的,但在记录和复制的目的上被视为安全:
CONNECTION_ID(),CURDATE(),CURRENT_DATE(),CURRENT_TIME(),CURRENT_TIMESTAMP(),CURTIME(),,LAST_INSERT_ID(),LOCALTIME(),LOCALTIMESTAMP(),NOW(),UNIX_TIMESTAMP(),UTC_DATE(),UTC_TIME(), 和UTC_TIMESTAMP()。更多信息,请参见 Section 19.5.1.14, “Replication and System Functions”。
-
系统变量的引用。 大多数系统变量在基于语句的格式下无法正确复制。参见 Section 19.5.1.39, “复制和变量”。特殊情况请参见 Section 7.4.4.3, “混合二进制日志格式”。
-
可加载函数。 由于我们无法控制可加载函数的操作,因此必须假定它执行不安全的语句。
-
全文插件。 此插件在不同的 MySQL 服务器上可能表现不同;因此,依赖于它的语句可能会产生不同的结果。因此,在 MySQL 中,所有依赖全文插件的语句都被视为不安全。
-
触发器或存储过程更新具有 AUTO_INCREMENT 列的表。 这是不安全的,因为更新行的顺序可能在源和副本上不同。
此外,对具有包含不是此复合键的第一列的 AUTO_INCREMENT 列的复合主键的表进行
INSERT是不安全的。更多信息,请参见 Section 19.5.1.1, “复制和 AUTO_INCREMENT”。
-
对具有多个主键或唯一键的表执行 INSERT ... ON DUPLICATE KEY UPDATE 语句。 当针对包含多个主键或唯一键的表执行此语句时,此语句被视为不安全,因为存储引擎检查键的顺序是不确定的,MySQL 服务器更新的行取决于此顺序。
对于具有多个唯一或主键的表进行
INSERT ... ON DUPLICATE KEY UPDATE语句在基于语句的复制中被标记为不安全。 (Bug #11765650, Bug #58637) -
使用 LIMIT 进行更新。 检索行的顺序未指定,因此被视为不安全。参见 Section 19.5.1.18, “复制和 LIMIT”。
-
访问或引用日志表。 系统日志表的内容可能在源和副本之间不同。
-
事务操作后的非事务操作。 在事务中,允许任何非事务读取或写入在任何事务读取或写入之后执行被视为不安全。
更多信息,请参见 Section 19.5.1.35, “复制和事务”。
-
访问或引用自记录表。 对自记录表的所有读取和写入都被视为不安全。在事务中,对自记录表的读取或写入后的任何语句也被视为不安全。
-
LOAD DATA 语句。
LOAD DATA被视为不安全,当binlog_format=MIXED时,该语句以基于行的格式记录。当binlog_format=STATEMENT时,LOAD DATA不会生成警告,与其他不安全语句不同。 -
XA 事务。 如果在源端并行提交的两个 XA 事务在副本上以相反顺序准备,那么在基于语句的复制中可能会出现无法安全解决的锁定依赖关系,并且可能导致副本上的复制失败并发生死锁。当
binlog_format=STATEMENT时,XA 事务内的 DML 语句被标记为不安全并生成警告。当binlog_format=MIXED或binlog_format=ROW时,XA 事务内的 DML 语句使用基于行的复制记录,并且潜在问题不存在。 -
DEFAULT子句指的是一个不确定性函数。 如果表达式的默认值指向一个不确定性函数,任何导致表达式被评估的语句对于基于语句的复制都是不安全的。这包括诸如INSERT、UPDATE和ALTER TABLE等语句。与大多数其他不安全语句不同,这类语句在基于行的格式中无法安全复制。当binlog_format设置为STATEMENT时,该语句被记录并执行,但会在错误日志中写入警告消息。当binlog_format设置为MIXED或ROW时,该语句不会被执行,并且会在错误日志中写入错误消息。有关显式默认值处理的更多信息,请参见 MySQL 8.0.13 中的显式默认值处理。
更多信息,请参见第 19.5.1 节,“复制功能和问题”。
19.2.2 复制通道
原文:
dev.mysql.com/doc/refman/8.0/en/replication-channels.html
19.2.2.1 单个通道操作命令
19.2.2.2 与先前复制语句的兼容性
19.2.2.3 启动选项和复制通道
19.2.2.4 复制通道命名约定
在 MySQL 多源复制中,副本会打开多个复制通道,每个通道对应一个源服务器。复制通道代表从源到副本流动的事务路径。每个复制通道都有自己的接收器(I/O)线程、一个或多个应用程序(SQL)线程和中继日志。当来自源的事务被通道的接收器线程接收时,它们被添加到通道的中继日志文件中,并传递给通道的应用程序线程。这使得每个通道可以独立运作。
本节描述了通道在复制拓扑中的使用方式,以及它们对单源复制的影响。有关配置多源复制的源和副本、启动、停止和重置多源副本以及监视多源复制的说明,请参见第 19.1.5 节,“MySQL 多源复制”。
在多源复制拓扑中,一个副本服务器上可以创建的通道的最大数量为 256。每个复制通道必须具有唯一(非空)的名称,如第 19.2.2.4 节,“复制通道命名约定”中所解释的。启用多源复制时发出的错误代码和消息指定生成错误的通道。
注意
多源副本上的每个通道必须从不同的源复制。您不能从单个副本设置多个复制通道到单个源。这是因为副本的服务器 ID 在复制拓扑中必须是唯一的。源仅通过副本的服务器 ID 来区分副本,而不是通过复制通道的名称,因此它无法识别来自同一副本的不同复制通道。
多源复制副本还可以设置为多线程副本,方法是将系统变量replica_parallel_workers(从 MySQL 8.0.26 开始)或slave_parallel_workers(在 MySQL 8.0.26 之前)设置为大于 0 的值。当在多源复制副本上执行此操作时,副本上的每个通道都具有指定数量的应用程序线程,以及一个协调器线程来管理它们。无法为各个通道配置应用程序线程的数量。
从 MySQL 8.0 开始,可以在特定复制通道上配置多源复制副本的复制过滤器。当相同数据库或表存在于多个源上时,可以使用特定通道的复制过滤器,只需将副本从一个源复制即可。对于基于 GTID 的复制,如果同一事务可能来自多个源(例如在钻石拓扑中),必须确保所有通道上的过滤设置相同。有关更多信息,请参见 Section 19.2.5.4,“基于复制通道的过滤器”。
为了与旧版本兼容,MySQL 服务器在启动时自动创建一个名为空字符串("")的默认通道。该通道始终存在;用户无法创建或销毁它。如果没有创建其他通道(具有非空名称),则复制语句仅在默认通道上执行,以便所有来自旧副本的复制语句都能正常运行(参见 Section 19.2.2.2,“与先前复制语句的兼容性”)。本节描述的应用于复制通道的语句仅在至少有一个命名通道时才能使用。