参考官方文档:
https://dev.mysql.com/doc/refman/5.7/en/replication-implementation.html
16.2 复制实施
复制基于主服务器,在其二进制日志中跟踪其数据库的所有更改(更新,删除等)。二进制日志用作从服务器启动时起修改数据库结构或内容(数据)的所有事件的书面记录。通常,不会记录SELECT语句,因为它们既不修改数据库结构也不修改内容。
连接到主服务器的每个从服务器都请求二进制日志的副本。也就是说,它从主设备中提取数据,而不是主设备将数据推送到从设备。从服务器还从它接收的二进制日志中执行事件。这具有重放原始更改的效果,就像它们在主服务器上进行一样。创建表或修改其结构,并根据初在主服务器上进行的更改来插入,删除和更新数据。
由于每个从站都是独立的,因此从主站的二进制日志中重放的更改将在连接到主站的每个从站上独立发生。此外,由于每个从服务器仅通过从主服务器请求二进制日志的副本来接收二进制日志的副本,因此从服务器能够按照自己的进度读取和更新数据库的副本,并且可以随意启动和停止复制过程而不会影响主或者从
16.2.1 复制格式
复制的工作是因为写入二进制日志的事件是从主服务器读取的,然后在从服务器上处理。 根据事件的类型,事件以不同的格式记录在二进制日志中。 使用的不同复制格式对应于事件记录在主二进制日志中时使用的二进制日志记录格式。 二进制日志记录格式与复制期间使用的术语之间的关联是:
- 使用基于语句的二进制日志记录时,主服务器会将SQL语句写入二进制日志。通过在从站上执行SQL语句,将主站复制到从站。这称为基于语句的复制(可以缩写为SBR),它对应于基于MySQL语句的二进制日志记录格式。
- 使用基于行的日志记录时,主服务器会将事件写入二进制日志,以指示各个表行的更改方式。通过将代表行更改的事件复制到从属服务器,来完成主从复制。这称为基于行的复制(可以缩写为RBR)。
- 您还可以将MySQL配置为使用基于语句和基于行的日志记录的混合,具体取决于哪个适合要记录的更改。这称为混合格式日志记录。使用混合格式日志记录时,默认情况下使用基于语句的日志。根据某些语句以及正在使用的存储引擎,在特定情况下,日志会自动切换到基于行的语句。使用混合格式的复制称为基于混合的复制或混合格式复制。
在MySQL 5.7.7之前,基于语句的格式是默认格式。 在MySQL 5.7.7及更高版本中,基于行的格式是默认格式。
使用MIXED格式时,二进制日志记录格式部分取决于正在使用的存储引擎和正在执行的语句。
通过设置binlog_format服务器系统变量来控制正在运行的MySQL服务器中的日志记录格式。 可以使用会话或全局范围设置此变量。 管理新设置何时以及如何生效的规则与其他MySQL服务器系统变量相同。 为当前会话设置变量仅持续到该会话结束,并且该更改对其他会话不可见。 全局设置变量对更改后连接的客户端生效,但不会对任何当前客户端会话(包括更改变量设置的会话)生效。 要使全局系统变量设置为性以便在服务器重新启动时应用,必须在选项文件中进行设置。
在某些情况下,您无法在运行时更改二进制日志记录格式,否则会导致复制失败。 请参见第5.4.4.2节“设置二进制日志格式”。
更改全局binlog_format值需要足以设置全局系统变量的权限。 更改会话binlog_format值需要足以设置受限会话系统变量的权限。 请参见第5.1.8.1节“系统变量权限”。
基于语句和基于行的复制格式具有不同的问题和限制。 有关它们相对优缺点的比较,请参见第16.2.1.1节“基于语句和基于行的复制的优点和缺点”。
使用基于语句的复制,您可能会遇到复制存储的例程或触发器的问题。 您可以通过使用基于行的复制来避免这些问题。 有关更多信息,请参见第23.7节“存储程序的二进制日志记录”。
16.2.1.1 语句-基础和行-基础复制的优缺点
基于语句复制的优点
- 成熟的技术。
- 写入日志文件的数据较少。 当更新或删除影响许多行时,这会导致日志文件所需的存储空间大大减少。 这也意味着可以更快地完成从备份中获取和恢复。
- 日志文件包含进行任何更改的所有语句,因此可用于审核数据库。
基于语句复制的缺点
- 对于SBR 语句来说语句是不安全的。并非所有修改数据的语句(例如INSERT DELETE,UPDATE和REPLACE语句)都可以使用基于语句的复制进行复制。 使用基于语句的复制时,任何非确定性行为都难以复制。 此类数据修改语言(DML)语句的示例包括以下内容:
- 取决于UDF或存储程序的语句是不确定的,因为这样的UDF或存储程序返回的值或取决于提供给它的参数以外的因素。 (但是,基于行的复制只是复制UDF或存储程序返回的值,因此它对主表和从表的表行和数据的影响是相同的。)
- 使用不带ORDER BY的LIMIT子句的DELETE和UPDATE语句是不确定的。
- 使用基于语句的复制无法正确复制使用以下任何功函数语句:
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()
SLEEP()
VERSION()
使用基于语句的复制无法正确复制的语句将记录如下所示的警告:
[Warning] Statement is not safe to log in statement format.
在这种情况下,也会向客户发出类似的警告。 客户端可以使用SHOW WARNINGS显示它。
- INSERT ... SELECT需要比基于行的复制更多的行级锁。
- UPDATE语句需要进行表扫描(因为WHERE子句中没有使用索引)必须锁定比基于行的复制更多的行。
- 对于InnoDB:使用AUTO_INCREMENT的INSERT语句会阻止其他非冲突的INSERT语句。
- 对于复杂语句,必须在更新或插入行之前在从属服务器上评估和执行该语句。 对于基于行的复制,从属服务器只需修改受影响的行,而不是执行完整语句。
- 如果从站的评估中存在错误,特别是在执行复杂语句时,基于语句的复制可能会逐渐增加受影响行中的错误量。
- 存储的函数使用与调用语句相同的NOW()值执行。 但是,存储过程并非如此。
- 必须在从站上应用确定性UDF。
- 表定义在主服务器和从服务器上必须(几乎)相同。
基于行复制的优势
- 可以复制所有更改。 这是安全的复制形式。
注意:
更新mysql数据库中信息的语句(如GRANT,REVOKE和触发器操作,存储例程(包括存储过程)和视图)都使用基于语句的复制复制到从属服务器。
对于诸如CREATE TABLE ... SELECT之类的语句,将从表定义生成CREATE语句使用基于语句的格式进行复制,而使用基于行的格式复制行插入。
- 对于以下类型的语句,主服务器上需要更少的行锁,从而实现更高的并发性:
- INSERT ... SELECT
- 使用AUTO_INCREMENT的INSERT语句
- 使用WHERE子句的UPDATE或DELETE语句不使用key或检索的大部分行不发生更改。
- 对于任何INSERT,UPDATE或DELETE语句,从站上需要更少的行锁。
基于行复制的劣势
- RBR可以生成更多必须log的数据。 要复制DML语句(例如UPDATE或DELETE语句),基于语句的复制仅将语句写入二进制日志。 相比之下,基于行的复制将每个更改的行写入二进制日志。 如果语句更改了许多行,则基于行的复制可能会将更多数据写入二进制日志; 即使对于回滚的语句也是如此。 这也意味着制作和恢复备份可能需要更多时间。 此外,二进制日志被锁定较长时间来写入数据,这可能会导致并发问题。 使用binlog_row_image = minimal可以大大减少缺点。
- 与基于语句的复制相比,生成大型BLOB值的确定性UDF使用基于行的复制需要更长的时间。 这是因为记录了BLOB列值,而不是生成数据的语句。
- 您无法在从站上看到从主站接收和执行的语句。 但是,您可以使用mysqlbinlog以及--base64-output = DECODE-ROWS和--verbose选项查看更改了哪些数据。
或者,使用binlog_rows_query_log_events变量,如果启用,则在使用-vv选项时将该语句添加到mysqlbinlog输出的Rows_query事件。
- 对于使用MyISAM存储引擎的表,当将INSERT语句作为基于行的事件应用于二进制日志而不是将它们作为语句应用时,INSERT语句的从属服务器需要更强的锁定。 这意味着在使用基于行的复制时,不支持在MyISAM表上进行并发插入。
16.2.1.2 使用基于行的记录和复制
MySQL使用基于语句的日志记录(SBL),基于行的日志记录(RBL)或混合格式日志记录。 使用的二进制日志类型会影响日志记录的大小和效率。因此,基于行的复制(RBR)或基于语句的复制(SBR)之间的选择取决于您的应用程序和环境。
- 对于临时表,基于行的记录。如第16.4.1.30节“复制和临时表”中所述,使用基于行的格式时不会复制临时表。 使用混合格式日志记录时,使用基于语句的格式记录涉及临时表的“安全”语句。
使用基于行的格式时不会复制临时表,因为没有必要。另外,因为临时表只能从创建它们的线程中读取,所以即使使用基于语句的格式,也很少从复制它们中获得任何好处。
在MySQL 5.7中,即使创建了临时表,也可以从基于语句的二进制日志记录模式切换到基于行的二进制日志记录模式。但是,在使用基于行的格式时,MySQL服务器无法确定创建给定临时表时生效的日志记录模式。因此,在这种情况下,服务器会为该会话结束时为给定客户端会话仍然存在的每个临时表记录DROP TEMPORARY TABLE IF EXISTS语句。虽然这意味着在某些情况下可能会记录不必要的DROP TEMPORARY TABLE语句,但该语句是无害的,并且即使表不存在也不会导致错误,因为存在IF EXISTS选项。
注意:
从MySQL 8.0开始,此行为已更改,因为MySQL服务器跟踪在创建每个临时表时生效的日志记录模式。 因此,不必为每个临时表记录DROP TEMPORARY TABLE IF EXISTS语句。 从该版本开始,当给定的客户端会话结束时,服务器会为每个仍然存在的临时表记录DROP TEMPORARY TABLE IF EXISTS语句,该语句是在使用基于语句的二进制日志记录时创建的。 如果在创建表时使用基于行或混合格式的二进制日志记录,则不会记录DROP TEMPORARY TABLE IF EXISTS语句。
当使用binlog_format = ROW时,允许涉及临时表的非事务性DML语句,只要受语句影响的任何非事务性表都是临时表(Bug#14272672)。
- RBL和非事务表的同步
当许多行受到影响时,更改集将拆分为多个事件; 当语句提交时,所有这些事件都写入二进制日志。 在从属服务器上执行时,会对所有涉及的表执行表锁定,然后以批处理模式应用这些行。 根据用于表拷贝的引擎,这可能有效,也可能。
- 延迟和二进制日志大小
RBL将每行的更改写入二进制日志,因此其大小可以非常快速地增加。 这会显着增加在从站上进行更改以匹配主站上的更改所需的时间。 您应该知道应用程序中可能出现此延迟。
- 读取二进制日志。
mysqlbinlog使用BINLOG语句在二进制日志中显示基于行的事件(请参见第13.7.6.1节“BINLOG语法”)。 此语句将事件显示为基本64位编码的字符串,其含义不明显。 当使用--base64-output = DECODE-ROWS和--verbose选项调用时,mysqlbinlog将二进制日志的内容格式化为人类可读的。 当二进制日志事件以基于行的格式写入并且您希望从复制或数据库故障中读取或恢复时,可以使用此命令读取二进制日志的内容。
- 二进制日志 执行错误 和 slave_exec_mode
使用slave_exec_mode = IDEMPOTENT通常仅对MySQL NDB Cluster复制有用,IDEMPOTENT是默认值。 (请参见第21.6.10节“NDB集群复制:多主机和循环复制”)。 当slave_exec_mode为IDEMPOTENT时,无法从RBL应用更改,因为无法找到原始行不会触发错误或导致复制失败。 这意味着可能未在从站上应用更新,因此主站和从站不再同步。 当slave_exec_mode为IDEMPOTENT时,延迟问题和使用RBR的非事务表会导致主服务器和从服务器进一步分歧。
对于其他情况,将slave_exec_mode设置为STRICT通常就足够了; 这是NDB以外的存储引擎的默认值。
- 不支持基于服务器ID的过滤。
您可以使用CHANGE MASTER TO语句的IGNORE_SERVER_IDS选项根据服务器ID进行筛选。 此选项适用于基于语句和基于行的日志记录格式。 筛选某些从属服务器上的更改的另一种方法是使用WHERE子句,该子句包含关系@@ server_id <> id_value子句和UPDATE和DELETE语句。 例如,WHERE @@ server_id <> 1.但是,对于基于行的日志记录,这不能正常工作。 要使用server_id系统变量进行语句筛选,请使用基于语句的日志记录。
- 数据库级别复制选项
--replicate-do-db, - replicate-ignore-db和--replicate-rewrite-db选项的效果差别很大,具体取决于是使用基于行还是基于语句的日志记录。 因此,建议避免使用数据库级选项,而是使用表级选项,例如--replicate-do-table和--replicate-ignore-table。
- RBL,非事务性表和停止slave
使用基于行的日志记录时,如果从属服务器在从属线程更新非事务性表时停止,则从属数据库可能会达到不一致状态。 因此,建议您对使用基于行的格式复制的所有表使用InnoDB等事务存储引擎。 在关闭从属MySQL服务器之前使用STOP SLAVE或STOP SLAVE SQL_THREAD有助于防止出现问题,并且无论您使用何种日志格式或存储引擎,都始终建议使用它。
16.2.1.3 在二进制日志中确定安全和非安全的语句
MySQL Replication中语句的“安全性”是指是否可以使用基于语句的格式正确复制语句。 如果对于该语句是正确的,我们将该语句称为安全; 否则,我们称之为不安全。
处理安全和不安全的语句。 根据语句是否被认为是安全的,以及二进制日志记录格式(即binlog_format的当前值),对语句的处理方式也不同。
- 使用基于行的日志记录时,对安全和不安全语句的处理没有区别。
- 使用混合格式日志记录时,使用基于行的格式记录标记为不安全的语句; 使用基于语句的格式记录被视为安全的语句。
- 使用基于语句的日志记录时,标记为不安全的语句会生成对此效果的警告。 安全语句通常会被记录。
标记为不安全的每个语句都会生成警告。以前,如果在主服务器上执行了大量此类语句,则可能导致错误日志文件过大。为了防止这种情况,MySQL 5.7提供了一种警告抑制机制,其行为如下:每当50个近的ER_BINLOG_UNSAFE_STATEMENT警告在任何50秒的时间段内生成超过50次时,都会启用警告抑制。激活后,这会导致不将这些警告写入错误日志;相反,对于此类型的每50个警告,注释将在后S秒内重复N次的后警告写入错误日志。只要近50次这样的警告在50秒或更短时间内发出,这种情况就会持续下去;一旦费率降低到此阈值以下,警告将再次正常记录。警告抑制不会影响如何确定基于语句的日志记录的语句安全性,也不会影响警告如何发送到客户端。 MySQL客户端仍会收到每个此类语句的一个警告。
语句被认为不安全。
具有以下特征的陈述被认为是不安全的:
- 包含可能在从站上返回不同值的系统函数的语句。
这些函数包括FOUND_ROWS(),GET_LOCK(),IS_FREE_LOCK(),IS_USED_LOCK(),LOAD_FILE(),MASTER_POS_WAIT(),PASSWORD(),RAND(),RELEASE_LOCK(),ROW_COUNT(),SESSION_USER(),SLEEP() ,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().
- 对系统变量的引用
使用基于语句的格式无法正确复制大多数系统变量。
- UDFs
由于我们无法控制UDF的作用,因此我们必须假设它正在执行不安全的语句。
- 触发器活存储过程更新一个有AUTO_INCREMENT 字段的表
这是不安全的,因为更新行的顺序可能在主服务器和从服务器上有所不同。
此外,对具有复合主键的表的INSERT是不安全的,如果该复合主键的列的不是AUTO_INCREMENT字段。
- 在键或者复合主键的表上的 INSERT ... ON DUPLICATE KEY UPDATE 语句
对包含复合主键或键的表执行时,此语句被认为是不安全的,对存储引擎检查键的顺序很敏感,这不是确定性的,通过MYSQL 服务器依赖 选择行更新。 (Bug#11765650,Bug#58637)
- 使用 LIMIT 的更新。
未指定检索行的顺序,因此被视为不安全。
- 访问或关联 log 表
主站和从站之间的系统日志表的内容可能不同。
- 在事务性操作之后的非事务性操作
在事务中,允许在任何事务性读取或写入之后执行任何非事务性读取或写入被认为是不安全的。
- LOAD DATA INFILE 语句 。
LOAD DATA INFILE被视为不安全,当binlog_format = mixed时,语句以基于行的格式记录。 当binlog_format = statement时,LOAD DATA INFILE不会生成警告,与其他不安全的语句不同。
- XA 事务
如果正在主服务器上以并行顺序准备两个并行提交的XA事务,则基于语句的复制无法安全地解决锁定依赖关系,并且复制可能会因从服务器上的死锁而失败。 设置binlog_format = STATEMENT时,XA事务中的DML语句被标记为不安全并生成警告。 当设置binlog_format = MIXED或binlog_format = ROW时,使用基于行的复制记录XA事务中的DML语句,不存在潜在问题。
16.2.2 复制实施细节
MySQL复制功能使用三个线程实现,一个在主服务器上,两个在从服务器上:
- binglog dump 线程。
主设备创建一个线程,以便在从设备连接时将二进制日志内容发送到从设备。 在主服务器上的SHOW PROCESSLIST的输出中将此线程标识为 Binlog Dump 线程。
二进制日志转储线程获取主机二进制日志上的锁,用于读取要发送到从机的每个事件。 一旦事件被读取,即使在事件发送到从站之前,锁也会被释放。
- Slave I/O 线程。
在从属服务器上发出START SLAVE语句时,从属服务器会创建一个I / O线程,该线程连接到主服务器并要求它发送二进制日志中的更新记录。
slave I / O线程读取主机的Binlog dump 线程发送的更新(请参阅上一项)并将它们复制到包含slave 中继日志的本地文件。
该线程的状态在SHOW SLAVE STATUS的输出中显示为Slave_IO_running,或者在SHOW STATUS的输出中显示为Slave_running。
- Slave SQL 线程
从站创建一个SQL线程来读取由从I / O线程写入的中继日志,并执行其中包含的事件。
在前面的描述中,每个主/从连接有三个线程。 具有多个从站的主站为每个当前连接的从站创建一个二进制日志转储线程,每个从站都有自己的I / O和SQL线程。
从站使用两个线程将读取更新与主站分开,并将它们执行到独立任务中。 因此,如果语句执行缓慢,则不会减慢读取语句的任务。 例如,如果从服务器尚未运行一段时间,则当从服务器启动时,其I / O线程可以快速从主服务器获取所有二进制日志内容,即使SQL线程远远落后。 如果从服务器在SQL线程执行了所有获取的语句之前停止,则I / O线程至少已获取所有内容,以便语句的安全副本本地存储在从属的中继日志中,准备在下次在slave启动时执行。
SHOW PROCESSLIST语句提供的信息可以告诉您主服务器和从服务器上有关复制的信息。
如果主站侧有足够的时间在Binlog转储线程上没有活动,则主站确定从站不再连接。 对于任何其他客户端连接,此超时取决于net_write_timeout和net_retry_count的值;
16.2.3 复制通道
MySQL 5.7.6引入了复制通道的概念,它表示从主服务器到从服务器的事务路径。
为了提供与先前版本的兼容性,MySQL服务器在启动时自动创建一个默认通道,其名称为空字符串("")。 这个通道总是存在; 它不能被用户创建或销毁。 如果没有创建其他通道(具有非空名称),则复制语句仅作用于缺省通道,以便旧版从属的所有复制语句按预期运行(请参见第16.2.3.2节“与先前复制语句的兼容性”。 只有当至少有一个命名通道时,才能使用本节所述的复制通道。
复制通道包含从主设备传输到从设备的事务路径。 在多源复制中,从站打开多个通道,,每个通道都有自己的中继日志和应用程序(SQL)线程。 一旦复制通道的接收器(I / O)线程接收到事务,它们就会被添加到通道的中继日志文件中并传递给应用程序线程。 这使通道能够独立运行。
复制通道还与主机名和端口关联。 您可以将多个通道分配给主机名和端口的相同组合; 在MySQL 5.7中,可以在多源复制拓扑中被添加的一个从站的大通道数为256.每个复制通道必须具有(非空)名称(请参见第16.2.3.4节“复制通道命名约定”))。 通道可以独立配置。
16.2.3.1 在单个通道上的单一操作
要使MySQL复制操作能够在单个复制通道上执行操作,请将FOR CHANNEL通道子句与以下复制语句一起使用:
- CHANGE MASTER TO
- START SLAVE
- STOP SLAVE
- SHOW RELAYLOG EVENTS
- FLUSH RELAY LOGS
- SHOW SLAVE STATUS
- RESET SLAVE
同样,为以下函数引入了一个额外的channel参数:
- MASTER_POS_WAIT()
- WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS()
从MySQL 5.7.9开始,group_replication_recovery通道不允许使用以下语句。
- START SLAVE
- STOP SLAVE
16.2.3.2 与先前复制语句的兼容性
当复制从站具有多个通道且未指定FOR CHANNEL通道选项时,有效语句通常作用于所有可用通道。
例如,以下语句按预期运行:
- START SLAVE启动除group_replication_recovery通道之外的所有通道的复制线程。
- STOP SLAVE会停止所有通道的复制线程,但group_replication_recovery通道除外。
- SHOW SLAVE STATUS报告所有通道的状态。
- FLUSH RELAY LOGS刷新所有通道的中继日志。
- RESET SLAVE重置所有通道。
某些复制语句无法在所有通道上运行。 在这种情况下,错误1964从站上存在多个通道。 请提供频道名称作为参数。 生成。 在多源复制拓扑中使用时,以下语句和函数会生成此错误,并且不使用FOR CHANNEL通道选项指定要对其执行的通道:
- SHOW RELAYLOG EVENTS
- CHANGE MASTER TO
- MASTER_POS_WAIT()
- WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS()
- WAIT_FOR_EXECUTED_GTID_SET()
请注意,默认通道始终存在于单个源复制拓扑中,其中语句和函数的行为与以前的MySQL版本相同。
16.2.3.3 启动选项和复制通道
本节介绍受添加复制通道影响的启动选项。
必须正确配置以下启动选项才能使用多源复制。
- --relay-log-info-repository
必须将其设置为TABLE。 如果此选项设置为FILE,则尝试向从站添加更多源将失败,并显示ER_SLAVE_NEW_CHANNEL_WRONG_REPOSITORY。
- --master-info-repository
必须将其设置为TABLE。 如果此选项设置为FILE,则尝试向从站添加更多源将失败,并显示ER_SLAVE_NEW_CHANNEL_WRONG_REPOSITORY。
以下启动选项现在会影响复制拓扑中的所有通道。
- --log-slave-updates
从站接收的所有事务(甚至来自多个源)都写入二进制日志中。
- --relay-log-purge
设置后,每个通道自动清除自己的中继日志。
- --slave_transaction_retries
所有通道的应用程序线程重试事务。
- --skip-slave-start
没有复制线程在任何通道上启动。
- --slave-skip-errors
执行继续,并且所有通道都会跳过错误。
为以下启动选项设置的值适用于每个通道; 由于这些是mysqld启动选项,因此它们适用于每个通道。
- --max-relay-log-size=size
每个通道的单个中继日志文件的大大小; 达到此限制后,文件将被轮询。
- --relay-log-space-limit=size
对于每个单独的通道,所有中继日志的总大小的上限。 对于N个通道,这些日志的组合大小限制为relay_log_space_limit * N.
- --slave-parallel-workers=value
每个通道的从站并行工作器数。
- --slave-checkpoint-group
每个源的I / O线程等待时间。
- --relay-log-index=filename
每个通道的中继日志索引文件的基本名称。
- --relay-log=filename
表示每个通道的中继日志文件的基本名称。
- --slave_net-timeout=N
每个通道设置此值,以便每个通道等待N秒以检查连接是否断开。
- --slave-skip-counter=N
每个通道设置此值,以便每个通道从其master跳过N个事件。
16.2.3.4 复制通道命名约定
本节介绍命名约定如何受复制通道的影响。
每个复制通道都有一个的名称,该名称是一个大长度为64个字符的字符串,不区分大小写。 由于通道名称用于slave 表,因此用于这些的字符集始终为UTF-8。 虽然您通常可以自由地为频道使用任何名称,但保留以下名称:
- group_replication_applier
- group_replication_recovery
您为复制通道选择的名称也会影响多源复制从站使用的文件名。 每个通道的中继日志文件和索引文件名为relay_log_basename-channel.xxxxxx,其中relay_log_basename是使用--relay-log选项指定的基本名称,channel是记录到此文件的通道的名称。 如果未指定--relay-log选项,则使用默认文件名,该名称也包括通道的名称。
16.2.4 复制延迟和状态日志
在复制期间,从属服务器会创建多个日志,这些日志包含从主服务器中继到从服务器的二进制日志事件,并记录有关中继日志中当前状态和位置的信息。 此过程中使用了三种类型的日志,如下所示:
- 主信息日志包含从站与主站连接的状态和当前配置信息。 此日志包含有关主主机名,登录凭据和坐标的信息,这些坐标指示从站从主站的二进制日志中读取的距离。
通过使用--master-info-repository = TABLE启动slave,可以将此日志写入mysql.slave_master_info表而不是文件。
- 中继日志包括从主站的二进制日志中读取并由从站I / O线程写入的事件。 作为SQL线程的一部分,中继日志中的事件在从属服务器上执行。
- 中继日志信息日志保存有关从属中继日志中的执行点的状态信息。
通过使用--relay-log-info-repository = TABLE启动从站,可以将此日志写入mysql.slave_relay_log_info表而不是文件。
当表用于从属状态日志时,如果mysqld无法初始化复制日志记录表,则会发出警告,但允许从属服务器继续启动。 从不支持从属日志记录表的MySQL版本升级到支持它们的MySQL版本时,有可能发生这种情况。
重要:不要手动尝试更新或插入行到 slave_master_info 或 slave_relay_log_info 表中。这样做可能会导致未定义的行为,并且不受支持。
在复制正在进行时,不允许执行任何需要对slave_master_info和slave_relay_log_info表中的任何一个或两者执行写锁定的语句,而在任何时候都允许执行仅执行读取的语句。
如果将master_info_repository和relay_log_info_repository设置为TABLE,则使用事务存储引擎InnoDB创建mysql.slave_master_info和mysql.slave_relay_log_info表。 作为表,中继日志信息日志的更新与事务一起提交,这意味着记录在该日志中的从属进度信息始终与应用于数据库的内容一致,即使在服务器意外停止的情况下也是如此。 必须在从站上启用--relay-log-recovery选项以保证弹性。
16.2.4.1 Slave Relay Log
与二进制日志一样,中继日志由一组编号文件和一个索引文件组成,这些文件包含描述数据库更改的事件,索引文件包含所有使用的中继日志文件的名称。
术语“中继日志文件”通常表示包含数据库事件的单个编号文件。 术语“中继日志”统一表示编号的中继日志文件集加上索引文件。
中继日志文件具有与二进制日志文件相同的格式,可以使用mysqlbinlog读取
缺省情况下,中继日志文件名在数据目录中的格式为host_name-relay-bin.nnnnnn,其中host_name是从服务器主机的名称,nnnnnn是序列号。 连续的中继日志文件使用连续的序列号创建,从000001开始。从站使用索引文件来跟踪当前正在使用的中继日志文件。 缺省中继日志索引文件名是在数据目录中的host_name-relay-bin.index。
如果从站使用默认的基于主机的中继日志文件名,则在设置复制后更改从站的主机名可能会导致复制失败,并显示 Failed to open the relay log 和 Could not find target log during relay log initialization。 这是一个已知问题(参见Bug#2122)。 如果您预计将来可能会更改从属主机名(例如,如果在从属设备上建立网络以便可以使用DHCP修改其主机名),则可以通过使用--relay- log和--relay-log-index选项来完全避免此问题,用于在初设置从站时明确指定中继日志文件名。 这将使名称独立于服务器主机名更改。
如果在复制已经开始之后遇到问题,解决此问题的一种方法是停止从属服务器,将旧的中继日志索引文件的内容添加到新服务器,然后重新启动从属服务器。 在Unix系统上,这可以如下所示完成:
shell> cat new_relay_log_name.index >> old_relay_log_name.index
shell> mv old_relay_log_name.index new_relay_log_name.index
从服务器在以下条件下创建新的中继日志文件:
- 每次I/O线程启动时。
- 刷新日志时; 例如,使用FLUSH LOGS或mysqladmin flush-logs。
- 当前中继日志文件的大小变得“太大”时,被下列参数确定:
- 如果max_relay_log_size的值大于0,那么这是大中继日志文件大小。
- 如果max_relay_log_size的值为0,则max_binlog_size确定大中继日志文件大小。
SQL线程在执行文件中的所有事件并且不再需要它之后,会自动删除每个中继日志文件。 没有明确的机制来删除中继日志,因为SQL线程负责这样做。 但是,FLUSH LOGS会轮换中继日志,这会影响SQL线程何时删除它们。
16.2.4.2 Slave Status Logs
复制从属服务器创建两个日志。 默认情况下,这些日志是名为http://master.info和http://relay-log.info的文件,并在数据目录中创建。 可以分别使用--master-info-file和--relay-log-info-file选项更改这些文件的名称和位置。 通过使用适当的选项启动服务器,也可以将这些日志中的任何一个或两个写入mysql数据库中的表:使用--master-info-repository将主信息日志写入mysql.slave_master_info表,并使用 - -relay-log-info-repository将中继日志信息日志写入mysql.slave_relay_log_info表。
这两个状态日志包含SHOW SLAVE STATUS语句输出中显示的信息,这将在第13.4.2节“控制从属服务器的SQL语句”中讨论。 由于状态日志存储在磁盘上,因此它们在从服务器关闭后仍然存在。 下一次从站启动时,它会读取两个日志,以确定从主站读取二进制日志和处理自己的中继日志的进度。
如果将master_info_repository和relay_log_info_repository设置为TABLE,则使用事务存储引擎InnoDB创建mysql.slave_master_info和mysql.slave_relay_log_info表。 作为表,中继日志信息日志的更新与事务一起提交,这意味着记录在该日志中的从属进度信息始终与应用于数据库的内容一致,即使在服务器意外停止的情况下也是如此。 必须在从站上启用--relay-log-recovery选项以保证弹性。
创建一个供内部使用的附加从属状态日志,并保存有关多线程复制从属上的工作线程的状态信息。 此从属工作日志包括每个工作线程的中继日志文件和主二进制日志文件的名称和位置。 如果将从站的中继日志信息日志创建为表,则将从属工作日志写入mysql.slave_worker_info表。 如果将中继日志信息日志写入文件,则将从属工作日志写入http://worker-relay-log.info文件。 对于外部使用,工作线程的状态信息显示在Performance Schema表replication_applier_status_by_worker中。
如果http://relay-log.info文件尚未刷新到磁盘,则http://relay-log.info文件的内容和SHOW SLAVE STATUS语句显示的状态可能不匹配。理想情况下,您应该只查看脱机的slave(即mysqld未运行)上的http://relay-log.info。对于正在运行的系统,如果要将状态日志写入表,则可以使用SHOW SLAVE STATUS,或查询slave_master_info和slave_relay_log_info表。
备份从属数据时,应备份这两个状态日志以及中继日志文件。从从站还原数据后,需要状态日志才能恢复复制。如果丢失了中继日志但仍有中继日志信息日志,则可以检查它以确定SQL线程在主二进制日志中执行了多远。然后,您可以将CHANGE MASTER TO与MASTER_LOG_FILE和MASTER_LOG_POS选项一起使用,以告知从属设备从该点重新读取二进制日志。当然,这要求主服务器上仍然存在二进制日志。
16.2.5 服务器如何评估 复制过滤规则
如果主服务器未将语句写入其二进制日志,则不会复制该语句。如果服务器记录了该语句,则该语句将发送到所有从站,并且每个从站确定是执行它还是忽略它。
在主服务器上,您可以使用--binlog-do-db和--binlog-ignore-db选项来控制要记录更改的数据库,以控制二进制日志记录。有关服务器在评估这些选项时使用的规则的说明,请参见第16.2.5.1节“数据库级复制和二进制日志记录选项的评估”。您不应使用这些选项来控制复制哪些数据库和表。相反,在从站上使用过滤来控制在从站上执行的事件。
在从端,关于是否执行或忽略从主服务器接收的语句的决定是根据从属服务器启动的--replicate- *选项进行的。 (请参见第16.1.6节“复制和二进制日志记录选项和变量”。)也可以使用CHANGE REPLICATION FILTER语句动态设置由这些选项控制的过滤器。无论是使用--replicate- *选项在启动时创建还是在通过CHANGE REPLICATION FILTER运行从属服务器时,管理此类过滤器的规则都是相同的。请注意,复制筛选器不能用于为组复制配置的MySQL服务器实例,因为在某些服务器上筛选事务会使组无法就一致状态达成协议。
在简单的情况下,当没有--replicate- *选项时,slave执行从主服务器接收的所有语句。否则,结果取决于给定的特定选项。
首先检查数据库级选项(--replicate-do-db,--replicate-ignore-db);有关此过程的说明,请参见第16.2.5.1节“数据库级复制和二进制日志选项的评估”。如果未使用任何数据库级选项,则选项检查将继续执行可能正在使用的任何表级选项(有关这些选项的讨论,请参见第16.2.5.2节“表级复制选项的评估”)。如果使用了一个或多个数据库级选项但未匹配任何选项,则不会复制该语句。
对于仅影响数据库的语句(即CREATE DATABASE,DROP DATABASE和ALTER DATABASE),数据库级选项始终优先于任何--replicate-wild-do-table选项。换句话说,对于此类语句,当且仅当没有适用的数据库级选项时,才会检查--replicate-wild-do-table选项。这是MySQL以前版本的行为更改,如果从属服务器启动了--replicate-do-db=dbx --replicate-wild-do-table = db%.t1,则不会复制语句CREATE DATABASE dbx。 T1。 (Bug#46110)
为了更容易确定选项集会产生什么影响,建议您避免混合使用“do”和“ignore”选项,或者使用wildcard和nonwildcard选项。
如果指定了任何--replicate-rewrite-db选项,则在测试--replicate- *过滤规则之前应用它们。
注意:
所有复制过滤选项都遵循相同的区分大小写规则,适用于MySQL服务器中其他位置的数据库和表的名称,包括lower_case_table_names系统变量的影响。