MySQL-11-配置复制拓扑结构

目标:

  • 描述 MySQL 主从复制
  • 解释复制在高可用性和可扩展性中的作用
  • 配置MySQL复制环境
  • 设计高级复制拓扑
  • 克隆MySQL数据

主从复制概述

MySQL复制概述

MySQL复制的一个特性是能让服务器从一个实例复制变化到另一个

  • 主机写入所有的数据和结构性变化到二进制日志

    • 二进制日志格式是基于语句、基于行或者混合格式
  • 从服务器(slave)会向主服务器请求二进制日志,并在本地应用其内容。

    • 它会跟踪所有已接收和已应用事件的状态,以便在服务器重启或网络故障后,能够从停止的位置继续(复制)。

    二进制日志格式:MySQL 支持基于语句、基于行以及混合格式的日志记录,具体内容将在本课程后续的 “二进制日志格式” 幻灯片中介绍。

    网络中断:MySQL 复制可应对网络中断情况。每个从服务器会跟踪其已处理的日志进度,当网络连接恢复时,会自动恢复处理(日志)。此行为是自动的,无需特殊配置。

复制的主服务器与从服务器

主 / 从关系通常是一对多的:

  • 每个从服务器从一个主服务器读取日志。
  • 一个主服务器可以向多个从服务器发送日志。

MySQL 支持多源复制:

  • 一个从服务器可以从多个主服务器进行复制。

从服务器数量

单个主服务器可拥有的从服务器数量没有限制。然而,每增加一个从服务器都会在主服务器上占用少量资源,因此在生产环境中,你应仔细权衡每个从服务器带来的收益。在特定环境中,一个主服务器的最佳从服务器数量取决于多个因素:架构大小、写入操作数量、主服务器和从服务器的相对性能,以及 CPU 和内存可用性等因素。一般的指导原则是,将每个主服务器的从服务器数量限制在不超过 30 个

注意:通常一个从服务器仅从单个主服务器进行复制。不过,在多源复制场景中,一个从服务器可以从多个主服务器进行复制。

中继从服务器(Relay Slaves)

  • 中继从服务器是一种复制从服务器,它会充当另一个从服务器的复制主服务器。
  • 更改会传播到更多的从服务器。

中继从服务器详细说明

从服务器可以充当另一个从服务器的主服务器。最顶层主服务器上发生的更改,会由其直接连接的从服务器请求并应用,这些从服务器会将更改中继传递给它们的从服务器,依此类推,直到复制到达链的末端。这使得更新能够通过多层复制进行传播,支持更复杂的拓扑结构。每增加一层,都会给系统增加更多的传播延迟,因此,相比更深层次的设置,较浅层次的设置复制延迟更小。

复杂拓扑结构

可实现更复杂的拓扑结构:

  • 双向拓扑:包含两台主服务器,彼此互为对方的从服务器。
  • 环形拓扑:可包含任意数量的服务器。
    • 每台服务器既是另一台主服务器的主服务器,也是其从服务器。
    • 任意一台主服务器上的更改会复制到所有服务器。
    • 并非每个从服务器都必须充当主服务器。
  • 多源复制:允许一个从服务器接收来自多个主服务器的事务。

注意事项

标准 MySQL 复制不执行冲突解决。

复制冲突

复制冲突

在包含多个主服务器的复制拓扑中,可能会出现冲突。

  • 如果两个客户端几乎同时在两台主服务器上写入同一行数据,你无法预测从服务器上该行的最终值。
  • 最终值取决于中继从服务器上的事件排序。
    • 在分层复制中,从服务器上该行的最终值由层级结构决定:
      • 如果某个中间主服务器修改了该行,从服务器上的值将与主服务器不一致。
    • 在环形复制中,发生冲突时,不同服务器上该行的最终值会不一致。
      • 最终值取决于每个主服务器应用事件的顺序。
  • 标准 MySQL 复制不执行冲突解决。不过,MySQL 组复制(MySQL Group Replication)可以检测并预防冲突

冲突解决

在典型配置中,客户端仅向主服务器写入更改,但可从任意服务器读取更改。在服务器允许对相似数据进行并发更新的环境中,多台服务器上的数据最终状态可能会变得不一致。应用程序有责任预防或管理冲突操作。MySQL 复制不执行冲突解决。

复制冲突:无冲突的示例场景

  • “奢侈品牌(Luxury Brands)” 团队将奢侈产品的价格提高 20%(记为操作 L )。
  • “特别活动(Special Events)” 团队将价格超过 500 美元的产品降价 50 美元(记为操作 S )。
  • 有一款奢侈产品原价 520 美元,会受这两项变更影响。
  • 如果操作按 L 然后 S 的顺序执行,两台服务器上的最终价格都是 574 美元。
  • 如果操作按 S 然后 L 的顺序执行,两台服务器上的最终价格都是 564 美元。
详细示例

假设一家电商公司使用环形复制拓扑,其中两台服务器分别处理 “奢侈品牌” 和 “特别活动” 团队的应用。假设应用程序不管理冲突操作,发生以下事件:

  1. “奢侈品牌” 团队将奢侈产品的价格提高 20%。
  2. “特别活动” 团队因即将到来的特别假期,将所有价格超过 500 美元的产品降价 50 美元。
  3. 一款售价 520 美元的产品同时属于这两个类别,其价格会被上述两项操作更新。

产品在每台服务器上的最终价格取决于每台服务器执行操作的顺序。

  • 复制环境中的其他服务器会根据它们应用操作的顺序得到最终值。

类似地,如果 “奢侈品牌” 团队添加了一个新产品,但在 “特别活动” 团队进行变更时尚未完全复制,或者两个团队在不同服务器上添加了具有相同主键的产品,就会发生冲突。

由于 MySQL 服务器无法检测和解决复制冲突,应用程序必须处理所有可能发生的复制冲突。

给 MySQL 集群用户的注意事项:MySQL 集群在内部使用一种复制形式,这种复制在某些方面与 MySQL 服务器中的复制不同,并且提供冲突检测(以及可选的冲突解决)功能。

何时使用复制

复制的常见用途包括:

  • 水平扩展:将查询(读)工作负载分散到多个从服务器。
  • 商业智能与分析:在从服务器上运行耗时的报表和分析,让主服务器专注于生产应用。
  • 地理数据分布:通过本地应用为本地用户提供服务,并将商业智能数据复制到公司服务器。
  • 高可用性:在多台服务器之间提供冗余,便于受控切换或滚动升级。

用于水平扩展的复制

  • 将客户端查询负载分散到多台服务器:
    • 客户端将写操作发送到复制主服务器。
    • 客户端在复制从服务器之间分散读操作。
      • 使用负载均衡器或具备负载均衡功能的连接器。
  • 由于只有一台服务器接受写操作,不会发生冲突。
    • 但如果应用程序写入一个值后立即尝试再次读取该值,可能会出现不一致的情况。
  • 水平扩展并非透明的。你必须修改客户端,使其:
    • 向主服务器写数据
    • 从一组负载均衡的从服务器读数据
    • 处理因主服务器到从服务器的复制延迟而可能出现的不一致情况
水平扩展补充说明

实施复制最常见的原因是将查询工作负载分散到一台或多台从服务器,以提高整个应用中读操作的性能,并通过减少主服务器的读工作负载,提升主服务器上写操作的性能。

用于商业智能和分析的复制

  • 商业智能工作负载通常对事务性数据有不同的性能要求。
    • 因需从多张表读取大量行,所以需要高吞吐量
    • 包含聚合和汇总操作的长时间运行查询
  • 通过将商业智能数据复制到专用的分析从服务器,避免影响事务性工作负载。
    • 为不同业务单元使用多个从服务器。
    • 在每个从服务器上配置索引和存储引擎,以优化不同的分析需求。
      • 使用复制过滤器或 BLACKHOLE 存储引擎,避免复制不需要在每个从服务器上存储的表数据。
商业智能和分析补充说明

商业智能报表和分析处理可能会占用大量资源,且执行时间较长。在复制环境中,你可以在从服务器上运行此类查询,这样主服务器就能继续处理生产工作负载,而不会受到长时间运行且 I/O 密集型报表的影响。

用于地理数据分布的复制

  • 将与地理位置相关的数据存储在靠近其主要用户的服务器上。
    • 在每个位置使用水平扩展复制,为规模更大的本地用户群提高潜在吞吐量。
  • 将部分或全部此类数据复制到其他位置。
    • 将与位置无关的数据复制到所有位置。
      • 例如:用户、产品、类别、销售记录
    • 将汇总数据复制到公司中央服务器。
      • 例如:销售汇总、营销活动结果、库存数据

地理数据分布补充说明

对于在地理上分散布局的公司而言,复制能让其受益。这些公司可在每个地区部署服务器来处理本地数据,并在整个组织内复制这些数据。这样做既能因服务器靠近客户和员工而带来性能与管理上的优势,又能让公司掌握全局数据情况。

注意事项

多源复制非常适合地理上分散的服务器。

使用 BLACKHOLE 存储引擎进行复制

  • BLACKHOLE 存储引擎会默默丢弃所有数据更改,且不发出任何警告。
    • 它会接受插入或更新数据的 DML 请求,即便不存在任何匹配数据。
    • 它没有任何更高级的智能或功能。
  • 二进制日志会继续成功记录这些更改。
  • 当中继从服务器(relay slave)需将所有更改复制到下游从服务器,但自身无需在这些表中存储数据时,可对表使用 BLACKHOLE 存储引擎。
  • 传(日志)而不存(数据)

补充说明

可以使用复制过滤器阻止服务器复制某些数据,但如果需要将这些数据复制到下游从服务器,同时又不想在本地存储它,可使用 BLACKHOLE 存储引擎避免在本地保存该数据。

例如,若你有一个中继从服务器,仅用于对少量表执行频繁的长时间运行的商业智能报表任务,你可将所有其他复制的表配置为使用 BLACKHOLE 存储引擎,这样服务器就不会存储不需要的数据,同时仍会将所有更改复制到其从服务器。

用于高可用性的复制

复制支持多种高可用性用例:

  • 受控切换:在硬件或系统升级期间,使用副本服务器替代生产服务器。
  • 服务器冗余:发生系统故障时,故障转移到副本服务器。
  • 在线架构变更:在多服务器环境中执行滚动升级,避免整体系统停机。
  • 软件升级:在环境升级期间,跨不同版本的 MySQL 进行复制。
    • 从服务器必须运行比主服务器更新的版本。
    • 升级期间发出的查询必须受升级过程中使用的所有版本支持。

配置复制

配置复制

  1. 绘制复制拓扑图。
  2. 确定参与复制的所有服务器。
    • 注意:任何从其他主服务器复制的主服务器,同时也是一个复制从服务器(即级联复制中的中继主,兼具主、从身份 )。
  3. 为每个服务器配置唯一的server-id
    • 是一个无符号 32 位整数,默认值为 1。
    • 任何 server-id 为 0 的主服务器或从服务器,都会拒绝与其他服务器进行复制。
  4. 配置每个复制主服务器。
  5. 配置每个复制从服务器以连接到其主服务器。
  6. 使用 START SLAVE 语句在每个复制从服务器上启动复制。

配置复制主服务器

  • 启用 TCP/IP 网络。

    • 复制不能使用 UNIX 套接字文件。
  • 启用二进制日志。

    • 复制期间,每个主服务器会将其日志内容发送给每个从服务器。
  • 创建一个具有 REPLICATION SLAVE权限的用户。

    1
    2
    
    CREATE USER user@slave_hostname IDENTIFIED BY 'password';
    GRANT REPLICATION SLAVE ON *.* TO user@slave_hostname;
    
    • 每个从服务器必须连接到一个主服务器以从中复制数据。
    • 若主服务器有多个从服务器,可在主机名中指定通配符以匹配所有从服务器,或创建多个用户。
  • 备份主服务器数据库,作为从服务器的起始点。

    • 若不使用 GTID,需记录日志坐标。
      • 若使用 mysqldump,可使用 --master-data 选项。

补充说明

从 MySQL 8.0 开始,caching_sha2_password 身份验证插件是新建用户的默认插件。要连接到复制主服务器(使用该插件认证的用户账户 ),必须按照 https://dev.mysql.com/doc/refman/8.0/en/replication-solutions-encrypted-connections.html 中描述的方法,要么设置安全连接,要么启用未加密连接以支持使用 RSA 密钥对进行密码交换。

注意事项

GTID 指全局事务标识符。

若使用 GTID,备份中捕获的已执行 GTID 集合是配置从服务器所必需的。可以在 mysqldump 中使用 --set-gtid-purged 选项,控制生成的 SQL 脚本中的 SET @@GLOBAL.GTID_PURGED 命令。

配置复制从服务器

  • 恢复来自主服务器的备份。
    • 若使用 GTID,验证 gtid_purged 变量是否已设置。
  • 在每个从服务器上执行 CHANGE MASTER TO语句,包含以下信息:
    • 主服务器的网络位置
      • MASTER_HOSTMASTER_PORT 的值
      • 可选:使用 MASTER_SSL 及相关选项,在复制期间加密主从服务器之间的网络流量。
    • 具有REPLICATION SLAVE权限的复制账户用户名和密码
      • MASTER_USERMASTER_PASSWORD 的值
    • 开始复制的二进制日志坐标(若不使用 GTID )
      • MASTER_LOG_FILEMASTER_LOG_POS 的值存储了从服务器开始复制的二进制日志位置。
      • 若使用 GTID,指定 MASTER_AUTO_POSITION=1

注意事项

MASTER_SSL 及相关选项仅在启用了 SSL 的服务器上可用。

CHANGE MASTER TO

  • 在从服务器上执行 CHANGE MASTER TO... 语句,配置与主服务器的连接细节:

    1
    2
    3
    4
    5
    6
    7
    
    mysql> CHANGE MASTER TO
        ->     MASTER_HOST = 'host_name',
        ->     MASTER_PORT = port_num,
        ->     MASTER_USER = 'user_name',
        ->     MASTER_PASSWORD = 'password',
        ->     MASTER_LOG_FILE = 'master_log_name',
        ->     MASTER_LOG_POS = master_log_pos;
    
  • 后续执行 CHANGE MASTER TO 时,未指定的选项会保留其当前值。

    • 更改主服务器的主机或端口时,也会重置日志坐标。
    • 以下语句仅更改密码,但保留所有其他设置:
    1
    
    mysql> CHANGE MASTER TO MASTER_PASSWORD='newpass';
    

查找日志坐标

  • 在执行备份后,立即在主服务器上执行 SHOW MASTER STATUS

    • 确保备份后主服务器上没有活动,以保证日志坐标是备份前最后一个事件的坐标。
    • 示例:
    1
    2
    3
    4
    5
    6
    7
    
    mysql> SHOW MASTER STATUS;
    +------------------+----------+-------------------+-------------------+-------------------+
    | File             | Position | Binlog_Do_DB      | Binlog_Ignore_DB  | Executed_Gtid_Set |
    +------------------+----------+-------------------+-------------------+-------------------+
    | mysql-bin.000014 |     51467|                   |                   |                   |
    +------------------+----------+-------------------+-------------------+-------------------+
    1 row in set (#.## sec)
    
  • 使用 mysqldump 备份主服务器时,使用 --master-data 选项,以查找备份时的日志坐标。

全局事务标识符(GTIDs)

全局事务标识符(GTIDs)在复制拓扑中唯一标识每个事务。

  • 每个 GTID 的格式为<source-uuid>:<transaction-id>

    。例如:0ed18583-47fd-11e2-92f3-0019b944b7f7:338

  • 一个 GTID 集合包含一系列 GTID:0ed18583-47fd-11e2-92f3-0019b944b7f7:1-338

  • 使用以下选项启用 GTID 模式:

    • gtid-mode=ON:记录每个事务时,同时记录唯一的 GTID。
    • enforce-gtid-consistency:禁止无法以事务安全方式记录的事件。
    • log-slave-updates:将复制的事件记录到从服务器的二进制日志中。

补充说明

MySQL 服务器提供了一些内置函数来处理 GTID。

  • 1
    
      GTID_SUBSET(set1, set2)
    
    • 如果 set1 中的所有 GTID 也在 set2 中,返回 true;否则返回 false
  • 1
    
      GTID_SUBTRACT(set1, set2)
    
    • 返回 set1 中不在 set2 中的 GTID。
  • 1
    
      WAIT_FOR_EXECUTED_GTID_SET(gtid_set[, timeout])
    
    • 等待直到服务器应用了 gtid_set 中包含的所有事务的 GTID。

识别源服务器

server_uuid 值的相关说明:

  • 是存储在服务器数据目录中auto.cnf

    文件里的通用唯一标识符(UUID)。

    • 如果 auto.cnf 文件不存在,服务器会生成一个新的 auto.cnf 文件,其中包含新的 server_uuid 值。
    • 你可以通过查询同名的系统变量来查看 server_uuid 值:
    1
    2
    3
    4
    
    mysql> SELECT @@server_uuid\G
    *************************** 1. row ***************************
    @@server_uuid: 0ed18583-47fd-11e2-92f3-0019b944b7f7
    1 row in set (#.## sec)
    
  • 用于 GTID 中,记录事务最初是在哪个服务器上执行的。

  • 在复制链中的所有从服务器上保留,以便识别每个事务的原始主服务器。

记录事务

  • 当每个服务器执行一个事务时,它还会在 gtid_executed 变量中记录该事务的 ID。

    • 包含一组 GTID。
    • 表示来自本地服务器、直接主服务器以及任何其他上游主服务器的所有事务。
    1
    2
    3
    4
    5
    6
    
    mysql> SELECT @@global.gtid_executed\G
    *************************** 1. row ***************************
    @@global.gtid_executed: bac1b034d-4785-11e2-8fe9-0019b944b7f7:1-34,
    c237b5cd-4785-11e2-8fea-0019b944b7f7:1-9,
    c9cec614-4785-11e2-8fea-0019b944b7f7:1-839
    1 row in set (#.## sec)
    
  • 当二进制日志被清理(purged)时,GTID 集合会从二进制日志中移除,并存储在 gtid_purged 系统变量中。

  • 执行 RESET MASTER 会导致 gtid_executedgtid_purged 都被设置为空字符串。所有二进制日志文件也会被删除。

补充说明

每当二进制日志轮转(rotated)或服务器关闭时,服务器会将写入前一个二进制日志文件的所有事务的 GTID 写入 mysql.gtid_executed 表。

gtid_executed 变量是由 MySQL 服务器管理的只读变量,而 gtid_purged 是一个动态变量,你可以配置它来控制 GTID 复制从服务器。

在执行 RESET MASTER 之前,你可能需要备份二进制日志文件;在执行 RESET MASTER 之后,你可能需要备份数据库。

使用 GTID 的复制

使用 CHANGE MASTER TO... 语句启用 GTID 复制:

  • 告知从服务器事务由 GTID 标识:

    1
    
    CHANGE MASTER TO MASTER_AUTO_POSITION=1;
    
  • 无需提供主服务器的日志坐标(如 MASTER_LOG_FILEMASTER_LOG_POS ),因为从服务器会将 @@global.gtid_executed 的值发送给主服务器。因此:

    • 主服务器知道从服务器已执行哪些事务。
    • 主服务器仅发送从服务器尚未执行的事务。
  • 不能在同一个 CHANGE MASTER TO... 语句中同时提供 MASTER_AUTO_POSITION 和日志坐标

复制过滤规则

  • 使用复制过滤器控制复制的范围。
  • 过滤器是应用于主服务器或从服务器的服务器选项:
    • 主服务器在写入二进制日志时,应用 binlog-* 类型的过滤器。
    • 从服务器在读取中继日志时,应用 replicate-* 类型的过滤器。
  • 当环境中不同的从服务器有不同用途时使用这些过滤器。
    • 示例:
      • 负责显示网页内容的服务器不需要工资单或库存数据。
      • 为管理层提供销售数据的服务器不需要网页内容数据或营销数据。

应用过滤规则

  • 根据以下条件选择要复制的事件:
    • 数据库:
      • replicate-do-dbbinlog-do-db
      • replicate-ignore-dbbinlog-ignore-db
    • 表:
      • replicate-do-tablereplicate-wild-do-table
      • replicate-ignore-tablereplicate-wild-ignore-table
  • 应用过滤器时需考虑优先级规则:
    • 数据库过滤器在表过滤器之前应用。
    • 表通配符过滤器(*-wild-* )在非通配符表过滤器之后应用。
    • *-do-* 类型的过滤器在对应的 *-ignore-* 类型的过滤器之前应用。

补充说明

使用多个过滤器时要谨慎。由于过滤器的应用顺序复杂,很容易出错。因为过滤器控制着复制的数据,这类错误很难恢复。因此,不要混合使用不同类型的过滤器。例如,如果你使用 replicate-wild-*,就不要使用任何非通配符的 replicate-* 过滤器。

binlog_format 设置为 ROWMIXED 时,临时表不会被复制。当 binlog_format=STATEMENT 时,要抑制特定临时表的复制,可使用 replicate-ignore-tablereplicate-wild-ignore-table。其他复制过滤器对临时表无效。

二进制和复制日志

二进制日志格式

  • MySQL 在二进制日志中以三种不同格式之一记录信息:

    • 基于行的日志记录(默认方法 )
    • 基于语句的日志记录
    • 混合日志记录
  • 通过设置全局或会话级别的 binlog_format 服务器变量来更改二进制日志格式:

    1
    
    SET [GLOBAL|SESSION] BINLOG_FORMAT=[row|statement|mixed|default];
    
  • 在运行时,你无法在以下情况中设置 binlog_format 变量:

    • 在存储函数或触发器内部
    • 如果启用了 NDB 存储引擎
    • 如果会话当前正在使用基于行的复制且存在打开的临时表

基于行的二进制日志记录

  • 是默认的二进制日志记录格式。
  • 记录对单个表行的更改:
    • 当很多行被更新时,会生成更大的日志。
    • 日志中记录的值与发送到存储引擎的值完全相同。
    • 每个表需要有主键才能正确识别每一行。
    • 从服务器上需要的 DML(数据操作语言)锁更少。
  • 即使语句是非确定性的,也始终能正确重放语句:
    • 示例:CURRENT_USER()CONNECTION_ID()
补充说明

复制的源表和目标表不必完全相同。主服务器上的表可以比从服务器上的表副本有更多或更少的列。此外,在满足特定条件时,主服务器和从服务器上对应的表列可以使用不同的数据类型。有关可能的场景和条件,请参见 https://dev.mysql.com/doc/refman/en/replication-features-differing-tables.html

当使用基于行的复制时,你可以设置 slave_type_conversions 系统变量来控制从服务器上的数据类型转换模式。

基于语句的二进制日志记录

  • 包含实际的 SQL 语句
    • 可用于审计
    • 更容易为时间点恢复识别语句
  • 包含 DDL(如 CREATEDROP 等 )和 DML(如 UPDATEDELETE 等 )语句
  • 由于所需文件大小相对较小,节省磁盘空间和网络带宽
    • 当一条 SQL 语句修改许多行时
  • 无法保证非确定性语句在远程机器上正确重放
    • 如果 MySQL 无法做出此保证,会发出警告:该语句以语句格式记录可能不安全

混合格式二进制日志记录

  • 默认使用基于语句的日志记录方式。
  • 当语句具有非确定性时,使用基于行的日志记录方式,具体情形包括:
    • 调用 UUID()USER()CURRENT_USER()FOUND_ROWS()ROWS_COUNT() 函数,或者调用任何用户定义的函数。
    • 当更新包含 AUTO_INCREMENT 列的一个或多个表,且调用了触发器或存储函数时。
    • 当语句引用系统变量时。
    • 涉及视图或临时表的某些特定情况。
  • 当存储引擎不支持基于语句的日志记录方式时,使用基于行的日志记录方式,具体涉及:
    • NDB Cluster 存储引擎。
    • 隔离级别为 READ COMMITTED(读已提交)或 READ UNCOMMITTED(读未提交 )时的 InnoDB 存储引擎。

复制日志

从服务器维护有关复制事件的信息。

  • 中继日志集:
    • 包含中继日志和中继日志索引文件。
    • 包含来自主服务器的二进制日志事件的副本。
  • 从服务器状态日志:
    • 包含执行复制所需的信息:
      • 主服务器连接详细信息和日志坐标
      • 中继日志坐标
    • 存储在表(默认)或文件中:
      • MySQL 数据库中的 slave_master_infoslave_relay_log_info
      • 默认文件名:master.inforelay-log.info
补充说明

中继日志:MySQL 会自动管理中继日志文件集,当重放完所有事件后会删除文件,当前文件超过最大中继日志文件大小(或 max_relay_log_size=0 时同二进制日志大小)时会创建新文件。中继日志的存储格式与二进制日志相同,你可以用 mysqlbinlog 查看它们。从服务器会维护一个索引文件来跟踪中继日志文件。

中继日志默认命名为 <host_name>-relay-bin.xxxxxx,索引文件命名为 <host_name>-relay-bin.index。要让服务器配置不受潜在的主机名变更影响,可通过设置 --relay-log--relay-log-index 选项来更改这些主机名前缀。

从服务器状态日志:从服务器会存储有关如何连接到主服务器,以及主服务器二进制日志和从服务器中继日志的最近复制日志坐标的信息。

有两种这样的日志:

  • 主服务器信息日志:此日志包含主服务器的信息,包括主机名和端口、用于连接的凭据,以及最近下载的主服务器二进制日志的日志坐标。
  • 中继日志信息日志:此日志包含中继日志最近执行的坐标,以及从服务器复制的事件落后于主服务器的秒数。

崩溃安全的复制

  • 二进制日志具备崩溃安全性
    • MySQL 仅记录完整的事件或事务。
    • 使用 sync-binlog提升安全性。
      • 默认值为 1:最安全,操作系统在每个事务后写入文件。
      • 将值设为 0:性能最佳,但服务器崩溃时事务丢失的可能性最高,因为操作系统根据内部规则写入文件。
      • 将值设为大于 1 的任意数字:在执行该数量的事务后写入。
  • 将从服务器状态日志存储在表中以实现崩溃安全的复制
    • 选项:master-info-repositoryrelay-log-info-repository
      • 可能的值为 TABLE(默认 )和 FILE
      • TABLE 具备崩溃安全性。
  • 恢复中继日志以防止日志损坏
    • relay-log-recovery 选项设为 ON,以创建新的中继日志文件,并初始化 SQL 和 IO 线程,以便从服务器重启后继续复制。
崩溃安全的复制(补充说明)

与早期版本的 MySQL 相比,MySQL 8.0 已设置默认值,使复制具备崩溃安全性。

sync-binlog 变量现在默认值为 1,且 master-info-repositoryrelay-log-info-repository 均默认设为 TABLE

此外,二进制日志记录默认启用。

复制的类型

异步复制(Asynchronous Replication)

  • 从库请求二进制日志并应用其内容。
    • 从库通常会滞后于主库。
  • 主库不关心从库何时应用日志。
    • 主库无需等待从库,会继续运行。

在 MySQL 复制的默认配置中,主库服务器接收来自客户端的变更事件,提交这些事件并将其写入二进制日志。在一个单独的线程中,主库会将二进制日志流式传输给已连接的从库。由于主库提交变更时无需等待任何从库的响应,这种方式被称为异步复制。

最重要的是,这意味着当主库向应用程序报告事务提交成功时,从库可能尚未应用这些事务。通常情况下,这不会有问题。然而,如果主库在提交事务后崩溃,且该事务尚未复制到任何从库,那么即使应用程序已向用户报告成功,该事务也会丢失。

如果主库在提交事务前等待所有从库应用其变更,那么这种复制就会被称为同步复制。尽管 MySQL 复制默认不是同步的,但 MySQL NDB Cluster(NDB 集群)会使用同步复制来确保整个集群的数据一致性,而 MySQL 客户端请求是同步的,因为客户端在向服务器发出查询后会等待服务器响应

半同步复制(Semisynchronous Replication)

  • 需要在主库和至少一个从库上安装插件
  • 会阻塞每个主库事件,直到至少有一个从库接收到该事件
  • 如果发生超时,会切换为异步复制

在半同步复制过程中,主库在提交一个事务后会进入阻塞状态,直到至少有一个半同步从库确认自己也已接收到该事务。这意味着,当主库向应用程序报告(事务提交)成功时,至少有一个从库已接收到每个事务。如果主库在提交事务后因数据丢失而崩溃,且应用程序已向用户报告(事务提交)成功,那么该事务也会存在于至少一个从库上。

优缺点

  • 确保数据完整性
  • 会导致性能下降
    • 主库在提交事务前需等待从库响应。
      • 超时时间由 rpl_semi_sync_master_timeout 变量控制,默认值为 10000 毫秒(10 秒 )。
      • 若未收到响应,主库仍会提交事务,但会回退到异步模式。
    • 每个事务额外花费的时间包括:
      • 通过 TCP/IP 往返将提交信息发送给从库。
      • 从库将提交信息记录到其中继日志。
      • 主库等待从库对该提交的确认。
  • 主要适用于物理上集中部署、通过高速网络通信的服务器

启用半同步复制

  • 在主库和至少一个从库上安装以下插件:
    • 在主库上安装 rpl_semi_sync_master
    • 在一个或多个从库上安装 rpl_semi_sync_slave
  • 启用以下选项:
    • 在主库上启用 rpl_semi_sync_master_enabled
    • 在从库上启用 rpl_semi_sync_slave_enabled
  • 如有需要,配置 rpl_semi_master_timeout变量。
    • 指定主库等待半同步从库响应的时间长度。
      • 超过该时间后,主库会提交事务并回退到异步模式。
    • 默认值为 10000 毫秒(10 秒)

多源复制

  • 使复制从库能够同时接收来自多个主库的事务
    • 至少需要两个主库和一个从库。
    • 从库会为每个主库创建一个复制通道。
    • 从库必须使用基于表(TABLE-based)的存储库。
      • 多源复制与基于文件(FILE-based)的存储库不兼容。
  • 不尝试检测或解决冲突
    • 若需要此功能,由应用程序负责处理。
  • 支持以下场景:
    • 将多个服务器备份到单个服务器
    • 将多个服务器的数据整合到单个服务器
    • 合并表分片

避免冲突(Avoiding Conflicts)

可通过不从多个主库复制同一个表来避免冲突。

若需要将多个主库的同一个表复制到从库的单个表中,不同主库的行必须不重叠,且主库发出的任何更新操作必须限制在该主库对应的行范围内。

  • 可使用多列主键,其中一列用于标识主库。
  • 若使用基于语句的日志记录,所有 UPDATEDELETE 语句必须包含针对标识主库的列的 WHERE 子句。

注意事项(Note)

多源复制与自动定位(auto-positioning)兼容。

为基于 GTID 的主库配置多源复制(Configuring Multi-Source Replication for a GTID-Based Master)

  1. 通过设置 gtid_mode=ON,在主库上启用基于 GTID(全局事务标识符 )的事务。

  2. 创建一个复制用户。

  3. 验证从库是否使用基于表(TABLE-based)的复制存储库。

  4. 执行CHANGE MASTER TO...语句,通过 FOR CHANNEL <channel>子句为一个通道添加新的主库。

    • 示例:将主机名为master1、使用端口 3451 的新主库添加到通道master-1

      1
      2
      3
      4
      
      CHANGE MASTER TO MASTER_HOST='master1', MASTER_PORT=3451,
      MASTER_USER='rpl', MASTER_PASSWORD='pass',
      MASTER_AUTO_POSITION = 1
      FOR CHANNEL 'master-1';
      

为基于二进制日志的主库配置多源复制(Configuring Multi-Source Replication for a Binary Log Based Master)

  1. 通过 --log-bin 在主库上启用二进制日志记录。

  2. 创建一个复制用户。

  3. 记录当前的二进制日志文件和位置。

    • MASTER_LOG_FILEMASTER_LOG_POSITION
  4. 验证从库是否使用基于表(TABLE-based)的复制存储库。

  5. 执行CHANGE MASTER TO...语句,通过FOR CHANNEL <channel>

    子句为一个通道添加新的主库。

    • 示例:将主机名为 master1、使用端口 3451 的新主库添加到通道master-1

      1
      2
      3
      4
      
      CHANGE MASTER TO MASTER_HOST='master1', MASTER_PORT=3451,
      MASTER_USER='rpl', MASTER_PASSWORD='pass',
      MASTER_LOG_FILE='master1-bin.000003', MASTER_LOG_POS=719,
      FOR CHANNEL 'master-1';
      

在多源复制拓扑中控制从库(Controlling Slaves in a Multi-Source Replication Topology)

  • 若你在从库上启用了多个复制通道,可使用 FOR CHANNEL 子句,针对特定通道执行 START SLAVESTOP SLAVERESET SLAVE 操作。

  • 若不使用 FOR CHANNEL 子句,该语句会影响所有当前已配置的复制通道。

  • 示例:

    • 启动channel-1上的复制:

      1
      
      START SLAVE FOR CHANNEL 'channel-1';
      
    • 停止channel-1上的复制:

      1
      
      STOP SLAVE FOR CHANNEL 'channel-1';
      
    • 重置所有已配置的通道:

      1
      
      RESET SLAVE;
      

克隆 MySQL 数据

MySQL克隆插件

克隆 MySQL 服务器实例的数据。

  • 克隆的数据
    • 包含 InnoDB 中存储数据的物理快照,涵盖模式(schemas)、表(tables)、表空间(tablespaces)以及数据字典元数据(data dictionary metadata )。
    • 可用作数据目录来配置(provision)一个 MySQL 服务器。
  • 两种克隆方式
    • 本地克隆(Local cloning)
      • 将数据克隆到一个目录。
    • 远程克隆(Remote cloning)
      • 从远程 MySQL 服务器实例克隆数据。

MySQL 克隆插件自 MySQL 8.0.17 版本起可用

克隆克隆插件安装

插件必须安装在捐赠者(donor )和接收者(recipient )的 MySQL 服务器上。

使用以下方法之一加载克隆插件:

  • 在 MySQL 服务器启动时,使用 plugin-loadplugin-load-add 启动选项加载插件:

    1
    2
    
    [mysqld]
    plugin-load-add=mysql_clone.so
    
    • 将此内容添加到配置文件中,以便服务器每次重启时都会加载该插件。
  • 在运行时使用 INSTALL PLUGIN 语句加载插件:

    1
    
    mysql> INSTALL PLUGIN clone SONAME 'mysql_clone.so';
    
    • 这会将插件注册到 mysql.plugins 系统表中,以便在后续每次服务器重启时加载该插件。

插件库文件的基本名称是 mysql_clone.so 。文件后缀因平台而异(例如,Unix 及类 Unix 系统使用 .so ,Windows 系统使用 .dll )。

要验证插件是否安装成功,可查看 INFORMATION_SCHEMA.PLUGINS 表或使用 SHOW PLUGINS 语句。

1
2
3
4
5
6
7
8
mysql> SELECT PLUGIN_NAME, PLUGIN_STATUS
       FROM INFORMATION_SCHEMA.PLUGINS
       WHERE PLUGIN_NAME = 'clone';
+-------------+---------------+
| PLUGIN_NAME | PLUGIN_STATUS |
+-------------+---------------+
| clone       | ACTIVE        |
+-------------+---------------+

为用户授予权限(Granting Permissions to Users)

对于本地克隆(For local cloning): 执行克隆操作的用户需要 BACKUP_ADMIN 权限。

1
mysql> GRANT BACKUP_ADMIN ON *.* TO 'clone_user';

对于远程克隆(For remote cloning)

  • 在接收者(recipient )服务器中发起克隆操作的用户,需要 CLONE_ADMIN 权限(用于替换数据、在克隆操作期间阻塞 DDL,以及自动重启服务器 )。

    1
    
    mysql> GRANT CLONE_ADMIN ON *.* TO 'clone_user';
    
  • 捐赠者(donor )服务器中的用户账户,需要 BACKUP_ADMIN 权限(用于从捐赠者访问和传输数据,以及在克隆操作期间阻塞 DDL )。此账户必须允许来自接收者服务器的连接。

    1
    
    mysql> GRANT BACKUP_ADMIN ON *.* TO 'donor_user'@'recipient_host';
    

克隆本地数据(Cloning Local Data)

  • 将本地 MySQL 数据目录中的数据克隆到同一主机上的另一个目录。

  • 使用带有 LOCAL DATA DIRECTORY 选项的 CLONE 语句:

    1
    
    mysql> CLONE LOCAL DATA DIRECTORY = '/path/to/clone_dir';
    
    • 指定用于存储克隆数据的绝对目录。
    • 克隆目录(clone_dir )必须不存在,但指定的路径(/path/to )必须是已存在的路径。
  • 克隆的数据目录可用于配置(provision)一个 MySQL 服务器实例:

    1
    
    shell> mysqld --datadir=/path/to/clone_dir
    
    • 你需要配置其他必需的设置,如监听端口和套接字文件。

本地克隆操作不支持克隆位于数据目录之外的用户创建的表或表空间。所有用户创建的 InnoDB 表和表空间、InnoDB 系统表空间、重做日志(redo logs )和回滚表空间(undo tablespaces )会被克隆到指定目录。

克隆远程数据(Cloning Remote Data)

  • 将数据从远程 MySQL 服务器实例(捐赠者,donor)克隆到本地 MySQL 服务器实例(接收者,recipient)。

  • clone_valid_donor_list 全局变量设置为捐赠者主机和端口的列表。

    1
    
    mysql> SET GLOBAL clone_valid_donor_list = 'donor_host:3306';
    
    • 需要 SYSTEM_VARIABLES_ADMIN 权限。
  • 在接收者服务器上,使用带有 INSTANCE FROM 选项的 CLONE 语句:

    1
    2
    
    mysql> CLONE INSTANCE FROM 'donor_user'@'donor_host':3306 
           IDENTIFIED BY 'password';
    
    • 指定捐赠者的用户账户、密码、捐赠者服务器和端口号。
    • 克隆操作会删除接收者数据目录中现有的数据,用克隆的数据替换它,然后自动重启服务器。

远程克隆的条件

  • 捐赠者和接收者的 MySQL 服务器实例必须运行在相同的操作系统和平台上。
  • 接收者必须有足够的磁盘空间存储克隆的数据。
  • 如果捐赠者 MySQL 服务器实例包含位于数据目录之外的表空间,克隆操作必须能够写入那些目录。
  • 捐赠者上激活的插件(包括任何加密插件),也必须在接收者上激活。
  • 捐赠者和接收者必须具有相同的 MySQL 服务器字符集和排序规则。
  • 捐赠者和接收者需要有相同的 innodb_page_sizeinnodb_data_file_path 设置。
  • 如果克隆加密数据或页压缩数据,捐赠者和接收者必须有相同的文件系统块大小。
  • 对于页压缩数据,接收者的文件系统必须支持稀疏文件,且在接收者上执行孔冲压(hole punching)时需支持该操作。
  • 如果克隆加密数据,需要安全连接。
  • 接收者上的 clone_valid_donor_list 设置必须包含捐赠者的主机地址。
  • 不能有其他克隆操作正在运行。
  • 捐赠者和接收者的 max_allowed_packet 值至少为 2MB。

用于复制的克隆(Cloning for Replication)

  • 克隆可用于配置(provision)一台复制从库服务器。

  • 克隆操作会从捐赠者(donor)提取复制坐标(replication coordinates)并传输到接收者(recipient)。

  • 对于基于二进制日志的复制,查询 performance_schema.clone_status 表以检查二进制日志位置,并将文件名和位置替换到 CHANGE MASTER TO 语句中:

    1
    2
    3
    
    mysql> SELECT BINLOG_FILE, BINLOG_POSITION FROM performance_schema.clone_status;
    mysql> CHANGE MASTER TO MASTER_HOST = 'donor_host', ... 
           ->     MASTER_LOG_FILE = 'binlog_file', MASTER_LOG_POS = binlog_position;
    
  • 对于 GTID 复制,执行带有 MASTER_AUTO_POSITION=1CHANGE MASTER TO 语句:

    1
    
    mysql> CHANGE MASTER TO MASTER_HOST = 'master_host', ... , MASTER_AUTO_POSITION=1;
    

克隆插件的限制(Clone Plugin Limitations)

  • 克隆操作期间,所有 DDL(数据定义语言)操作会被阻塞,但允许并发执行 DML(数据操作语言)操作。
  • 仅克隆 InnoDB 表的数据。其他存储引擎的表会被克隆为空表(无数据 )。
  • 不克隆服务器配置。
  • 不克隆二进制日志。
  • 本地克隆不会克隆使用绝对路径创建的通用表空间。
  • 远程克隆不支持 X 协议端口。
  • 无法通过 MySQL Router 连接到捐赠者(donor)MySQL 服务器实例。
0 次浏览