宁波网络推广平台推荐公司,西安seo计费管理,网站开发交易平台,网站建设讠金手指科杰文章目录 一、复制#xff08;Replication#xff09;1、什么是复制2、复制的方式3、复制的数据同步类型3.1、异步复制3.2、半同步复制3.3、设计理念#xff1a;复制状态机——几乎所有的分布式存储都是这么复制数据的 4、基于binlog位点同步的主从复制原理4.1、异步复制示例… 文章目录 一、复制Replication1、什么是复制2、复制的方式3、复制的数据同步类型3.1、异步复制3.2、半同步复制3.3、设计理念复制状态机——几乎所有的分布式存储都是这么复制数据的 4、基于binlog位点同步的主从复制原理4.1、异步复制示例4.2、半同步复制示例4.3、基于binlog位点主从复制痛点分析 5、基于全局事务标识符GTID复制5.1、GTID结构5.2、GTID工作原理5.3、GTID的配置5.4、基于GTID主从复制示例5.4.1、主从切换演练 二、组复制Group Replication1、什么是组复制2、单主模式2.1、单主模式部署示例 3、多主模式3.1、多主模式部署示例 一、复制Replication
1、什么是复制 官网https://dev.mysql.com/doc/refman/8.0/en/replication.html MySQL Replication是官方提供的主从同步方案也是用的最广的同步方案。Replication(复制)使来自一个 MySQL数据库服务器称为源Source的数据能够复制到一个或多个 MySQL 服务器称为副本Replica。默认情况下复制是异步的副本不需要永久连接即可从源接收更新。根据配置您可以复制所有数据库、指定数据库甚至某个数据库中的指定表。 说明旧版本的 MySQL 复制将源Source称为主Master将副本Replica称为从Slave 复制的优势: 高可用通过配置一定的复制机制MySQL 实现了跨主机的数据复制从而获得一定的高可用能力如果需要获得更高的可用性只需要配置多个副本或者进行级联复制就可以达到目的。 性能扩展由于复制机制提供了多个数据备份可以通过配置一个或多个副本将读请求分发至副本节点从而获得整体上读写性能的提升。 异地灾备只需要将副本节点部署到异地机房就可以轻松获得一定的异地灾备能力。实际当中需要考虑网络延迟等可能影响整体表现的因素。 交易分离通过配置复制机制并将低频、大运算量的交易发送至副本节点执行就可以避免这些交易与高频交易竞争运算资源从而避免整体的性能问题。
缺点 没有故障自动转移容易造成单点故障 主库从库之间有主从复制延迟问题容易造成最终数据的不一致 从库过多对主库的负载以及网络带宽都会带来很大的负担
应用场景 电子商务平台 在电商平台中主从复制可以用于实现读写分离提高并发处理能力同时确保数据的一致性。 社交网络 在社交网络应用中可以利用主从复制来提供快速的读取服务同时将数据变更复制到从数据库以备份数据。 实时监控和报警系统 在监控系统中主从复制可以用于实现数据的分布式存储和快速数据查询。 新闻和媒体网站 在高访问量的新闻网站中可以使用主从复制来提供高可用性和快速的内容访问。 金融服务 在金融行业数据的安全性和可用性至关重要主从复制可以用于数据备份和高可用性的实现。
2、复制的方式
MySQL 8.0支持多种复制方式
传统的方法是基于从源的二进制日志binlog复制事件并要求日志文件及其中的位置在源和副本之间进行同步。作为源(数据库更改发生的地方)的 MySQL 实例将更新和更改作为“事件”写入二进制日志。根据所记录的数据库更改二进制日志中的信息以不同的日志格式存储。副本配置为从源中读取二进制日志并在副本的本地数据库上执行二进制日志中的事件。
#获取binlog文件列表
mysql show binary logs;
#查看指定binlog文件的内容
mysql show binlog events in binlog.000003;官网https://dev.mysql.com/doc/refman/8.0/en/binlog-replication-configuration-overview.html 基于全局事务标识符(GTID)的方式。基于 GTID 的复制是完全基于事务的所以很容易确定源和副本是否一致; 只要在源上提交的所有事务也在副本上提交就可以保证两者之间的一致性。 官网https://dev.mysql.com/doc/refman/8.0/en/replication-gtids.html 3、复制的数据同步类型
MySQL 中的复制支持不同类型的同步。同步的原始类型是单向异步复制其中一个服务器充当源而一个或多个其他服务器充当副本。在 MySQL 8.0中除了内置的异步复制之外还支持半同步复制。使用半同步复制在返回执行事务的会话之前对源执行提交直到至少有一个副本确认它已经接收并记录了事务的事件。MySQL 8.0还支持延迟复制以使副本故意落后于源至少指定的时间。
3.1、异步复制
默认情况下MySQL 采用异步复制的方式执行事务操作的线程不会等复制 Binlog 的线程。具体的时序你可以看下面这个图 MySQL 主库在收到客户端提交事务的请求之后会先写入 Binlog然后再提交事务更新存储引擎中的数据事务提交完成后给客户端返回操作成功的响应。同时从库会有一个专门的复制线程从主库接收 Binlog然后把 Binlog 写到一个中继日志里面再给主库返回复制成功的响应。从库还有另外一个回放 Binlog 的线程去读中继日志然后回放 Binlog 更新存储引擎中的数据。
提交事务和复制这两个流程在不同的线程中执行互相不会等待这是异步复制。异步复制的劣势是可能存在主从延迟如果主节点宕机可能会丢数据。
3.2、半同步复制
MySQL 从 5.7 版本开始增加一种半同步复制Semisynchronous Replication的方式。这种机制与异步复制相比主要有如下区别 主节点在收到客户端的请求后必须在完成本节点日志写入的同时还需要等待至少一个从节点完成数据同步的响应之后或超时才会响应请求。 从节点只有在写入 relay-log 并完成刷盘之后才会向主节点响应。 当从节点响应超时时主节点会将同步机制退化为异步复制。在至少一个从节点恢复并完成数据追赶后主节点会将同步机制恢复为半同步复制。 可以看出相比于异步复制半同步复制在一定程度上提高了数据的可用性在未退化至异步复制时如果主节点宕机此时数据已复制至至少一台从节点。同时由于向客户端响应时需要从节点完成响应相比于异步复制此时多出了主从节点上网络交互的耗时以及从节点写文件并刷盘的耗时因此整体上集群对于客户端的响应性能表现必然有所降低。
半同步复制有两个重要的参数 rpl_semi_sync_master_wait_slave_count8.0.26之后改为rpl_semi_sync_source_wait_for_replica_count至少等待数据复制到几个从节点再返回。这个数量配置的越大丢数据的风险越小但是集群的性能和可用性就越差。 rpl_semi_sync_master_wait_point8.0.26之后改为rpl_semi_sync_source_wait_point这个参数控制主库执行事务的线程是在提交事务之前AFTER_SYNC等待复制还是在提交事务之后AFTER_COMMIT等待复制。默认是 AFTER_SYNC也就是先等待复制再提交事务这样就不会丢数据。
3.3、设计理念复制状态机——几乎所有的分布式存储都是这么复制数据的
在 MySQL 中无论是复制还是备份恢复依赖的都是全量备份和 Binlog全量备份相当于备份那一时刻的一个数据快照Binlog 则记录了每次数据更新的变化也就是操作日志。这种基于“快照 操作日志”的方法不是 MySQL 特有的。比如说Redis Cluster 中它的全量备份称为 Snapshot操作日志叫 backlog它的主从复制方式几乎和 MySQL 是一模一样的。Elasticsearch用的是 translog它备份和恢复数据的原理和实现方式也是完全一样的。
任何一个存储系统无论它存储的是什么数据用什么样的数据结构都可以抽象成一个状态机。存储系统中的数据称为状态也就是 MySQL 中的数据状态的全量备份称为快照Snapshot就像给数据拍个照片一样。我们按照顺序记录更新存储系统的每条操作命令就是操作日志Commit Log也就是 MySQL 中的 Binlog。 复制数据的时候只要基于一个快照按照顺序执行快照之后的所有操作日志就可以得到一个完全一样的状态。在从节点持续地从主节点上复制操作日志并执行就可以让从节点上的状态数据和主节点保持同步。
主从同步做数据复制时一般可以采用几种复制策略。 性能最好的方法是异步复制主节点上先记录操作日志再更新状态数据然后异步把操作日志复制到所有从节点上并在从节点执行操作日志得到和主节点相同的状态数据。异步复制的劣势是可能存在主从延迟如果主节点宕机可能会丢数据。 另外一种常用的策略是半同步复制主节点等待操作日志最少成功复制到 N 个从节点上之后再更新状态这种方式在性能、高可用和数据可靠性几个方面都比较平衡很多分布式存储系统默认采用的都是这种方式。
4、基于binlog位点同步的主从复制原理 1、主库会生成多个 binlog 日志文件。
2、从库的 I/O 线程请求指定文件和指定位置的 binlog 日志文件位点。
3、主库 dump 线程获取指定位点的 binlog 日志。
4、主库按照从库发送给来的位点信息读取 binlog然后推送 binlog 给从库。
5、从库将得到的 binlog 写到本地的 relay log (中继日志) 文件中。
6、从库的 SQL 线程读取和解析 relay log 文件。
7、从库的 SQL 线程重放 relay log 中的命令。
4.1、异步复制示例
1快速创建mysql实例 参考Docker安装MySQL8.0 利用Docker快速搭建Mysql8一主两从复制架构
角色server_idip:portmysql-source 主10192.168.65.185:3307mysql-replica1从111192.168.65.185:3308mysql-replica2从212192.168.65.185:3309
2 ) 配置mysql主从复制
主节点
2.1创建挂载目录
mkdir -p /mysql/replication/source/data /mysql/replication/source/conf /mysql/replication/source/log2.2准备配置文件
vim /mysql/replication/source/conf/custom.cnf
[mysql]
# 设置mysql客户端默认编码
default-character-setutf8[mysqld]
pid-file /var/run/mysqld/mysqld.pid
socket /var/run/mysqld/mysqld.sock
datadir /var/lib/mysqlsecure-file-priv NULL# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links0# 服务器唯一ID默认是1
server-id10# 启用二进制日志
log-binmysql-bin# 最大连接数
max_connections1000# 设置默认时区
default-time_zone8:00# 0:区分大小写
# 1:不区分大小写
lower_case_table_names1!includedir /etc/mysql/conf.d/ pid-file这是MySQL服务器的进程ID文件的位置。通过这个文件您可以在系统上找到正在运行的MySQL服务器的进程。 socket这是MySQL服务器用于本地通信的Unix套接字文件的位置。 datadir 这是MySQL服务器存储其数据文件的位置。 secure-file-priv 这是一个用于限制LOAD_FILE()和SELECT … INTO OUTFILE命令的文件路径。如果此选项被设置那么这两个命令只能用于读取在这个路径下的文件。设置为NULL表示禁用这个功能。 symbolic-links如果设置为0MySQL服务器将不允许在数据目录中使用符号链接。这有助于防止安全风险。 server-id每个MySQL服务器实例在复制时需要有一个唯一的ID。这有助于区分不同的服务器特别是在复制环境中。 log-bin启用二进制日志记录所有对数据库的更改这对于复制和恢复操作是必要的。 max_connections这是MySQL服务器可以接受的最大并发连接数。 default-time_zone这设置了MySQL服务器的默认时区。 lower_case_table_names这决定了MySQL如何存储和比较表名。设置为1意味着表名不区分大小写但在文件系统中它们仍然会区分大小写。 !includedir /etc/mysql/conf.d/这告诉MySQL服务器从/etc/mysql/conf.d/目录中包含其他配置文件。这意味着该目录下的任何.cnf或.ini文件都会被合并到这个主配置文件中。 replicate_do_db待同步的数据库日志 replicate_ignore_db不同步的数据库日志 2.3运行mysql容器
# 创建主从复制的网络
docker network create --driver bridge mysql-source-replica
#运行mysql容器
docker run -d \
--name mysql-source \
--privilegedtrue \
--restartalways \
--network mysql-source-replica \
-p 3307:3306 \
-v /mysql/replication/source/data:/var/lib/mysql \
-v /mysql/replication/source/conf:/etc/mysql/conf.d \
-v /mysql/replication/source/log:/logs \
-e MYSQL_ROOT_PASSWORD123456 \
-e TZAsia/Shanghai mysql:8.0.27 \
--lower_case_table_names1 2.4配置远程访问
docker exec -it mysql-source /bin/bash
mysql -u root -pALTER USER root% IDENTIFIED WITH mysql_native_password BY 123456;
flush privileges;从节点1
# 创建挂载目录
mkdir -p /mysql/replication/replica1/data /mysql/replication/replica1/conf /mysql/replication/replica1/log#准备配置文件
vim /mysql/replication/replica1/conf/custom.cnf
[mysql]
# 设置mysql客户端默认编码
default-character-setutf8[mysqld]
pid-file /var/run/mysqld/mysqld.pid
socket /var/run/mysqld/mysqld.sock
datadir /var/lib/mysqlsecure-file-priv NULL# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links0# 服务器唯一ID默认是1
server-id11# 启用二进制日志
log-binmysql-bin# 最大连接数
max_connections1000# 设置默认时区
default-time_zone8:00# 0:区分大小写
# 1:不区分大小写
lower_case_table_names1!includedir /etc/mysql/conf.d/#运行mysql容器
docker run -d \
--name mysql-replica1 \
--privilegedtrue \
--restartalways \
--network mysql-source-replica \
-p 3308:3306 \
-v /mysql/replication/replica1/data:/var/lib/mysql \
-v /mysql/replication/replica1/conf:/etc/mysql/conf.d \
-v /mysql/replication/replica1/log:/logs \
-e MYSQL_ROOT_PASSWORD123456 \
-e TZAsia/Shanghai mysql:8.0.27 \
--lower_case_table_names1 #配置远程访问
docker exec -it mysql-replica1 /bin/bash
mysql -u root -pALTER USER root% IDENTIFIED WITH mysql_native_password BY 123456;
flush privileges;从节点2
mkdir -p /mysql/replication/replica2/data /mysql/replication/replica2/conf /mysql/replication/replica2/log#准备配置文件
vim /mysql/replication/replica2/conf/custom.cnf
[mysql]
# 设置mysql客户端默认编码
default-character-setutf8[mysqld]
pid-file /var/run/mysqld/mysqld.pid
socket /var/run/mysqld/mysqld.sock
datadir /var/lib/mysqlsecure-file-priv NULL# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links0# 服务器唯一ID默认是1
server-id12# 启用二进制日志
log-binmysql-bin# 最大连接数
max_connections1000# 设置默认时区
default-time_zone8:00# 0:区分大小写
# 1:不区分大小写
lower_case_table_names1!includedir /etc/mysql/conf.d/#运行mysql容器
docker run -d \
--name mysql-replica2 \
--privilegedtrue \
--restartalways \
--network mysql-source-replica \
-p 3309:3306 \
-v /mysql/replication/replica2/data:/var/lib/mysql \
-v /mysql/replication/replica2/conf:/etc/mysql/conf.d \
-v /mysql/replication/replica2/log:/logs \
-e MYSQL_ROOT_PASSWORD123456 \
-e TZAsia/Shanghai mysql:8.0.27 \
--lower_case_table_names1 #配置远程访问
docker exec -it mysql-replica2 /bin/bash
mysql -u root -pALTER USER root% IDENTIFIED WITH mysql_native_password BY 123456;
flush privileges;3主库配置复制用户
每个副本使用一个 MySQL 用户名和密码连接到源因此在源上必须有一个用户帐户副本可以使用该帐户进行连接。
# 连接主库mysql-source
CREATE USER fox% IDENTIFIED WITH mysql_native_password BY 123456;
GRANT REPLICATION SLAVE ON *.* TO fox%;
flush privileges;4查看 master 机器的状态
使用 SHOW MASTER STATUS 语句确定当前二进制日志文件的名称和位置
# 主库上执行
SHOW MASTER STATUS;“文件”列显示日志文件的名称“位置”列显示文件内的位置。
5从节点设置主库信息 文档https://dev.mysql.com/doc/refman/8.0/en/replication-howto-slaveinit.html 在从库上执行 CHANGE REPLICATION SOURCE TO 语句(来自 MySQL 8.0.23)或 CHANGE MASTER TO语句(在 MySQL 8.0.23之前)
mysql CHANGE MASTER TO- MASTER_HOSTsource_host_name,- MASTER_USERreplication_user_name,- MASTER_PASSWORDreplication_password,- MASTER_LOG_FILErecorded_log_file_name,- MASTER_LOG_POSrecorded_log_position;Or from MySQL 8.0.23:
mysql CHANGE REPLICATION SOURCE TO- SOURCE_HOSTsource_host_name,- SOURCE_USERreplication_user_name,- SOURCE_PASSWORDreplication_password,- SOURCE_LOG_FILErecorded_log_file_name,- SOURCE_LOG_POSrecorded_log_position;从库1和从库2上执行
# from MySQL 8.0.23 执行下面的命令。
change replication source to source_host192.168.65.185, source_userfox, source_password123456, source_port3307, source_log_filemysql-bin.000003, source_log_pos1273, source_connect_retry30;source_host主数据库的IP地址 source_port主数据库的运行端口 source_user在主数据库创建的用于同步数据的用户账号 source_password在主数据库创建的用于同步数据的用户密码 source_log_file指定从数据库要复制数据的日志文件通过查看主数据的状态获取File参数 source_log_pos指定从数据库从哪个位置开始复制数据通过查看主数据的状态获取Position参数 source_connect_retry连接失败重试的时间间隔单位为秒。 6开启从库
#开启从库
start slave; 或者 start replica;
#查看从库状态
show slave status \G; 或者 show replica status \G;看到Replica_SQL_Running_State: Replica has read all relay log; waiting for more updates基本说明配置成功了已经开始了主从复制。
7测试主从复制功能
测试脚本
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS 0;CREATE DATABASE IF NOT EXISTS test;
USE test;
-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS user;
CREATE TABLE user (id int(0) NOT NULL AUTO_INCREMENT,name varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,address varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,last_updated bigint(0) NULL DEFAULT NULL,is_deleted int(0) NULL DEFAULT NULL,PRIMARY KEY (id) USING BTREE
) ENGINE InnoDB AUTO_INCREMENT 2 CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci ROW_FORMAT Dynamic;-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO user VALUES (2, 张三, 广州白云山, 1691563465, 0);SET FOREIGN_KEY_CHECKS 1;4.2、半同步复制示例 文档https://dev.mysql.com/doc/refman/8.0/en/replication-semisync-installation.html 1安装半同步插件
主节点
#from MySQL 8.0.26:
INSTALL PLUGIN rpl_semi_sync_source SONAME semisync_source.so;#验证是否成功安装
SELECT PLUGIN_NAME, PLUGIN_STATUSFROM INFORMATION_SCHEMA.PLUGINSWHERE PLUGIN_NAME LIKE %semi%;从节点
#from MySQL 8.0.26:
INSTALL PLUGIN rpl_semi_sync_replica SONAME semisync_replica.so;#验证是否成功安装
SELECT PLUGIN_NAME, PLUGIN_STATUSFROM INFORMATION_SCHEMA.PLUGINSWHERE PLUGIN_NAME LIKE %semi%;2开启半同步功能
主节点
SET GLOBAL rpl_semi_sync_source_enabled1;
#查看是否开启
show variables like %semi_sync%;从节点
set global rpl_semi_sync_replica_enabled1;3重启从节点上的I/O线程
如果在运行时启用副本上的半同步复制您还必须启动复制I/O(接收端)线程(如果已经运行则先停止它)以使副本连接到源端并注册为半同步副本。
STOP REPLICA IO_THREAD;
START REPLICA IO_THREAD;4半同步复制测试
测试当从节点响应超时时主节点会将同步机制退化为异步复制。 从节点恢复后同步机制是否会恢复为半同步复制
# 修改主节点半同步属性
set global rpl_semi_sync_source_wait_for_replica_count2;
set global rpl_semi_sync_source_timeout100000;#停掉从节点2
docker stop mysql-replica2#恢复从节点2
docker start mysql-replica2
#从节点2中执行
set global rpl_semi_sync_replica_enabled1;
STOP REPLICA IO_THREAD;
START REPLICA IO_THREAD;4.3、基于binlog位点主从复制痛点分析
痛点 1首次开启主从复制的步骤复杂 第一次开启主从同步时要求从库和主库是一致的。 找到主库的 binlog 位点。 设置从库的 binlog 位点。 开启从库的复制线程。
痛点 2恢复主从复制的步骤复杂 找到从库复制线程停止时的位点。 解决复制异常的事务。无法解决时就需要手动跳过指定类型的错误比如通过设置 slave_skip_errors1032,1062。当然这个前提条件是跳过这类错误是无损的。1062 错误是插入数据时唯一键冲突1032 错误是删除数据时找不到行
不论是首次开启同步时需要找位点和设置位点还是恢复主从复制时设置位点和忽略错误这些步骤都显得过于复杂而且容易出错。所以 MySQL 5.6 版本引入了 GTID彻底解决了这个困难。
5、基于全局事务标识符GTID复制 官网https://dev.mysql.com/doc/refman/8.0/en/replication-gtids.html GTID是一个基于原始mysql服务器生成的一个已经被成功执行的全局事务ID它由服务器ID以及事务ID组合而成。这个全局事务ID不仅仅在原始服务器器上唯一在所有存在主从关系 的mysql服务器上也是唯一的。正是因为这样一个特性使得mysql的主从复制变得更加简单以及数据库一致性更可靠。 一个GTID在一个服务器上只执行一次避免重复执行导致数据混乱或者主从不一致。 GTID用来代替传统复制方法不再使用MASTER_LOG_FILEMASTER_LOG_POS开启复制。而是使用MASTER_AUTO_POSTION1的方式开始复制。 在传统的replica端binlog是不用开启的但是在GTID中replica端的binlog是必须开启的目的是记录执行过的GTID强制。
GTID 的优势 更简单的实现 failover不用以前那样在需要找位点log_file 和 log_pos。 更简单的搭建主从复制。 比传统的复制更加安全。 GTID 是连续的没有空洞的保证数据的一致性零丢失。
5.1、GTID结构
GTID表示为一对坐标由冒号(:)分隔如下所示:
GTID source_id:transaction_idsource_id标识source服务器即源服务器唯一的server_uuid由于GTID会传递到replica所以也可以理解为源ID。 transaction_id是一个序列号由事务在源上提交的顺序决定。序列号的上限是有符号64位整数2^63-1
例如最初要在UUID为3E11FA47-71CA-11E1-9E33-C80AA9429562的服务器上提交的第23个事务具有此GTID
3E11FA47-71CA-11E1-9E33-C80AA9429562:23GTID集合是由一个或多个GTID或GTID范围组成的集合。来自同一服务器的一系列gtid可以折叠成单个表达式如下所示:
3E11FA47-71CA-11E1-9E33-C80AA9429562:1-5源自同一服务器的多个单一gtid或gtid范围也可以包含在单个表达式中gtid或范围以冒号分隔如下例所示:
3E11FA47-71CA-11E1-9E33-C80AA9429562:1-3:11:47-49GTID集合可以包括单个GTID和GTID范围的任意组合也可以包括来自不同服务器的GTID。
2174B383-5441-11E8-B90A-C80AA9429562:1-3, 24DA167-0C0C-11E8-8442-00059A3C7B00:1-19GTID存储在mysql数据库中名为gtid_executed的表中。该表中的一行包含它所代表的每个GTID或GTID集合的起始服务器的UUID以及该集合的开始和结束事务id。 5.2、GTID工作原理
主库计算主库 GTID 集合和从库 GTID 的集合的差集主库推送差集 binlog 给从库。
当从库设置完同步参数后主库 A 的 GTID 集合记为集合 x从库 B 的 GTID 集合记为 y。从库同步的逻辑如下 从库 B 指定主库 A基于主备协议建立连接。 从库 B 把集合 y 发给主库 A。 主库 A 计算出集合 x 和集合 y 的差集也就是集合 x 中存在集合 y 中不存在的 GTID 集合。比如集合 x 是 1~100集合 y 是 1~90那么这个差集就是 91~100。这里会判断集合 x 是不是包含有集合 y 的所有 GTID如果不是则说明主库 A 删除了从库 B 需要的 binlog主库 A 直接返回错误。 主库 A 从自己的 binlog 文件里面找到第一个不在集合 y 中的事务 GTID也就是找到了 91。 主库 A 从 GTID 91 的事务开始往后读 binlog 文件按顺序取 binlog然后发给 B。 从库 B 的 I/O 线程读取 binlog 文件生成 relay logSQL 线程解析 relay log然后执行 SQL 语句。
GTID 同步方案和位点同步的方案区别是 位点同步方案是通过人工在从库上指定哪个位点主库就发哪个位点不做日志的完整性判断。 而 GTID 方案是通过主库来自动计算位点的不需要人工去设置位点对运维人员友好。
5.3、GTID的配置
1修改主库配置
修改主库的配置文件
#GTID:
#启用全局事务标识符GTID模式
gtid_modeon
# 强制GTID的一致性。这意味着在执行事务时MySQL将确保所有涉及的服务器都使用相同的GTID集。
enforce_gtid_consistencyon 2修改从库配置
修改从库配置文件
#GTID:
gtid_modeon
enforce_gtid_consistencyon从节点设置主库信息
# 从库配置同步参数
mysql CHANGE MASTER TO MASTER_HOST host, MASTER_PORT port, MASTER_USER user, MASTER_PASSWORD password, MASTER_AUTO_POSITION 1; Or from MySQL 8.0.23:
mysql CHANGE REPLICATION SOURCE TO SOURCE_HOST host, SOURCE_PORT port, SOURCE_USER user, SOURCE_PASSWORD password, SOURCE_AUTO_POSITION 1;SOURCE_AUTO_POSITION 1 这告诉从服务器使用自动位置跟踪功能以便它可以自动从主服务器获取最新的二进制日志事件而无需手动指定位置。 5.4、基于GTID主从复制示例 文档https://dev.mysql.com/doc/refman/8.0/en/replication-gtids-howto.html 在前面基于binlog日志主从复制的mysql服务上配置GTID复制。
1同步所有的mysql服务器
在主从服务器上都执行下面的命令
# 设置MySQL服务器的全局只读模式
mysql SET GLOBAL.read_only ON;注意只有在使用已经在进行复制而不使用gtid的服务器时才需要此步骤。对于新服务器请继续执行步骤3。 2停止所有的服务器
docker stop mysql-source mysql-replica1 mysql-replica23主从节点都启用GTID
修改custom.cnf
# 启用GTID
gtid_modeON
enforce-gtid-consistencyON启动主从节点
docker start mysql-source mysql-replica1 mysql-replica24从节点配置基于GTID的自动定位
进入从节点执行下面命令
mysql stop replica;
mysql change replication source to source_host192.168.65.185, source_userfox, source_password123456, source_port3307,source_auto_position1;5开启从库复制并禁用只读模式
# 开启从库复制
mysql start replica;
# 只有在步骤1中将服务器配置为只读时才需要执行以下步骤。要允许服务器再次开始接受更新
mysql SET GLOBAL.read_only OFF;查看从库状态是否正常
mysql show replica status \G5.4.1、主从切换演练
场景1 模拟主库down机、从库1数据同步完成、从库2数据未同步完成
1从库2停止复制
mysql stop replica;2主库创建测试数据
INSERT INTO test.user VALUES (12, fox, NULL, NULL, NULL);3查询数据
从库1 从库2 很显然从库1同步了最新数据比从库2数据新
场景2 将主库宕机从库1升级为主库、从库2切换主库为从库1新的主库观察从库2是否同步未完成的事务
1停止主库
docker stop mysql-source2设置新主库
设置replica1 为replica2的主库因为replica1的数据是完整的。
按照普通复制方法需要计算主库的log_pos和从库设置成主库的log_pos可能出现错误
因为同一事务的GTID在所有节点上的值一致那么根据replica2当前停止点的GTID就能定位到要主库的GTID所以直接在replica2上执行change即可
# replica1上创建复制用户
CREATE USER fox% IDENTIFIED WITH mysql_native_password BY 123456;
GRANT REPLICATION SLAVE ON *.* TO fox%;
flush privileges;# replica2上执行 从replica1查询
mysql stop replica;
mysql change replication source to source_host192.168.65.185,source_port3308,source_userfox,source_password123456,source_auto_position1;
mysql start replica; 查询同步结果 场景3 模拟从库删除测试表主库对表进行插入操作。观察从库复制是否报错
1replica1删除test.user表主库插入新记录
# 从库1 删除user表
drop table test.user;
# 主库插入新记录
INSERT INTO test.user VALUES (14, AAA, NULL, NULL, NULL);2查看从库同步情况
# 从库1执行
mysql show replica status\G报错信息事务aac92b21-b6a4-11ee-bab5-0242ac120002:6执行失败
Coordinator stopped because there were error(s) in the worker(s). The most recent failure being: Worker 1 failed executing transaction ‘aac92b21-b6a4-11ee-bab5-0242ac120002:6’ at master log mysql-bin.000008, end_log_pos 1335. See error log and/or performance_schema.replication_applier_status_by_worker table for more details about this failure or others, if any.
3在主库继续进行其他事务观察gitd是否复制成功
# 主库插入新记录
INSERT INTO test.user VALUES (15, BBB, NULL, NULL, NULL);从库状态 可以看出从库复制中断 注意删除了表无法插入
4复制中断修复采用从库跳过错误事务修复
因为从库user表已经删了user表中部分数据不是利用gtid复制过去的先从主库将表数据拷贝到从库
获取从库最新状态 从库执行
# 1.停止从库1复制进程
mysql stop replica;
# 2.设置事务号事务号从 Retrieved_Gtid_Set 获取在session里设置gtid_next即跳过这个GTID
# 注意选择跳过出现错误的事务
mysql SET SESSION.GTID_NEXT aac92b21-b6a4-11ee-bab5-0242ac120002:7;
# 3.设置空事物
mysql BEGIN; COMMIT;
# 4.恢复自增事物号
mysql SET SESSION GTID_NEXT AUTOMATIC;
# 5.启动从库1复制进程
mysql start replica;
# 再次查询会发现主库数据已经同步过来了
mysql select * from test.user;如果需要一次跳过多条找出需要跳过的gtid批量执行
stop replica;
SET SESSION.GTID_NEXT d58e6bad-ef3e-11ee-8285-0242ac120003:4;begin;commit;
SET SESSION.GTID_NEXT d58e6bad-ef3e-11ee-8285-0242ac120003:5;begin;commit;
SET SESSION.GTID_NEXT d58e6bad-ef3e-11ee-8285-0242ac120003:6;begin;commit;
SET SESSION GTID_NEXT AUTOMATIC;
start replica;完整的演示步骤
1.从库删除user表
mysql drop table user;2.主库连续删除两条数据
mysql select * from user;
-------------------------------------------------------
| id | name | address | last_updated | is_deleted |
-------------------------------------------------------
| 2 | 张三 | 广州白云山 | 1691563465 | 0 |
| 3 | fox | NULL | NULL | NULL |
| 4 | 李四 | NULL | NULL | NULL |
| 5 | 111 | NULL | NULL | NULL |
| 12 | fox | NULL | NULL | NULL |
| 14 | AAA | NULL | NULL | NULL |
| 15 | BBB | NULL | NULL | NULL |
| 16 | CCC | NULL | NULL | NULL |
| 20 | DDD | NULL | NULL | NULL |
| 22 | EEE | NULL | NULL | NULL |
-------------------------------------------------------
10 rows in set (0.00 sec)mysql delete from user where id20;
Query OK, 1 row affected (0.19 sec)mysql select * from user;
-------------------------------------------------------
| id | name | address | last_updated | is_deleted |
-------------------------------------------------------
| 2 | 张三 | 广州白云山 | 1691563465 | 0 |
| 3 | fox | NULL | NULL | NULL |
| 4 | 李四 | NULL | NULL | NULL |
| 5 | 111 | NULL | NULL | NULL |
| 12 | fox | NULL | NULL | NULL |
| 14 | AAA | NULL | NULL | NULL |
| 15 | BBB | NULL | NULL | NULL |
| 16 | CCC | NULL | NULL | NULL |
| 22 | EEE | NULL | NULL | NULL |
| 23 | 333 | NULL | NULL | NULL |
-------------------------------------------------------
10 rows in set (0.00 sec)mysql delete from user where id22;
Query OK, 1 row affected (0.29 sec)mysql select * from user;
-------------------------------------------------------
| id | name | address | last_updated | is_deleted |
-------------------------------------------------------
| 2 | 张三 | 广州白云山 | 1691563465 | 0 |
| 3 | fox | NULL | NULL | NULL |
| 4 | 李四 | NULL | NULL | NULL |
| 5 | 111 | NULL | NULL | NULL |
| 12 | fox | NULL | NULL | NULL |
| 14 | AAA | NULL | NULL | NULL |
| 15 | BBB | NULL | NULL | NULL |
| 16 | CCC | NULL | NULL | NULL |
| 23 | 333 | NULL | NULL | NULL |
-------------------------------------------------------
9 rows in set (0.00 sec)3.借助Navicat将主库user表复制到从库包括数据。 这样一来从库就有了当前的全量数据只需要跳过错误的gtid从最新的gtid开始执行就可以了。
# 查询从库确定数据是否和主库一致
mysql select * from user;
-------------------------------------------------------
| id | name | address | last_updated | is_deleted |
-------------------------------------------------------
| 2 | 张三 | 广州白云山 | 1691563465 | 0 |
| 3 | fox | NULL | NULL | NULL |
| 4 | 李四 | NULL | NULL | NULL |
| 5 | 111 | NULL | NULL | NULL |
| 12 | fox | NULL | NULL | NULL |
| 14 | AAA | NULL | NULL | NULL |
| 15 | BBB | NULL | NULL | NULL |
| 16 | CCC | NULL | NULL | NULL |
| 23 | 333 | NULL | NULL | NULL |
-------------------------------------------------------
9 rows in set (0.00 sec)4.获取从库需要配置跳过错误的事务
# 获取到错误的gtid为d58e6bad-ef3e-11ee-8285-0242ac120003:12,
# 因为连续删除过两条数据所以d58e6bad-ef3e-11ee-8285-0242ac120003:13也是错误的事务
mysql show replica status\G;
*************************** 1. row ***************************Replica_IO_State: Waiting for source to send eventSource_Host: 192.168.65.223Source_User: foxSource_Port: 3308Connect_Retry: 30Source_Log_File: mysql-bin.000004Read_Source_Log_Pos: 4229Relay_Log_File: 3c946c781110-relay-bin.000012Relay_Log_Pos: 790Relay_Source_Log_File: mysql-bin.000004Replica_IO_Running: YesReplica_SQL_Running: NoReplicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 1146Last_Error: Coordinator stopped because there were error(s) in the worker(s). The most recent failure being: Worker 1 failed executing transaction d58e6bad-ef3e-11ee-8285-0242ac120003:12 at master log mysql-bin.000004, end_log_pos 3906. See error log and/or performance_schema.replication_applier_status_by_worker table for more details about this failure or others, if any.Skip_Counter: 0Exec_Source_Log_Pos: 3645Relay_Log_Space: 1932Until_Condition: NoneUntil_Log_File: Until_Log_Pos: 0Source_SSL_Allowed: NoSource_SSL_CA_File: Source_SSL_CA_Path: Source_SSL_Cert: Source_SSL_Cipher: Source_SSL_Key: Seconds_Behind_Source: NULL
Source_SSL_Verify_Server_Cert: NoLast_IO_Errno: 0Last_IO_Error: Last_SQL_Errno: 1146Last_SQL_Error: Coordinator stopped because there were error(s) in the worker(s). The most recent failure being: Worker 1 failed executing transaction d58e6bad-ef3e-11ee-8285-0242ac120003:12 at master log mysql-bin.000004, end_log_pos 3906. See error log and/or performance_schema.replication_applier_status_by_worker table for more details about this failure or others, if any.Replicate_Ignore_Server_Ids: Source_Server_Id: 11Source_UUID: d58e6bad-ef3e-11ee-8285-0242ac120003Source_Info_File: mysql.slave_master_infoSQL_Delay: 0SQL_Remaining_Delay: NULLReplica_SQL_Running_State: Source_Retry_Count: 86400Source_Bind: Last_IO_Error_Timestamp: Last_SQL_Error_Timestamp: 240401 14:17:40Source_SSL_Crl: Source_SSL_Crlpath: Retrieved_Gtid_Set: d58e6bad-ef3e-11ee-8285-0242ac120003:1-13,
dfb1f706-ef3e-11ee-82cc-0242ac120004:2Executed_Gtid_Set: ce6baf4a-ef3e-11ee-99fb-0242ac120002:1-13,
d58e6bad-ef3e-11ee-8285-0242ac120003:1-11,
dfb1f706-ef3e-11ee-82cc-0242ac120004:1-2Auto_Position: 1Replicate_Rewrite_DB: Channel_Name: Source_TLS_Version: Source_public_key_path: Get_Source_public_key: 0Network_Namespace:
1 row in set (0.00 sec)
5.在主库再次执行删除操作
mysql delete from user where id12;
Query OK, 1 row affected (0.11 sec)mysql select * from user;
-------------------------------------------------------
| id | name | address | last_updated | is_deleted |
-------------------------------------------------------
| 2 | 张三 | 广州白云山 | 1691563465 | 0 |
| 3 | fox | NULL | NULL | NULL |
| 4 | 李四 | NULL | NULL | NULL |
| 5 | 111 | NULL | NULL | NULL |
| 14 | AAA | NULL | NULL | NULL |
| 15 | BBB | NULL | NULL | NULL |
| 16 | CCC | NULL | NULL | NULL |
| 23 | 333 | NULL | NULL | NULL |
-------------------------------------------------------
6.在从库
mysql select * from user;
-------------------------------------------------------
| id | name | address | last_updated | is_deleted |
-------------------------------------------------------
| 2 | 张三 | 广州白云山 | 1691563465 | 0 |
| 3 | fox | NULL | NULL | NULL |
| 4 | 李四 | NULL | NULL | NULL |
| 5 | 111 | NULL | NULL | NULL |
| 12 | fox | NULL | NULL | NULL |
| 14 | AAA | NULL | NULL | NULL |
| 15 | BBB | NULL | NULL | NULL |
| 16 | CCC | NULL | NULL | NULL |
| 23 | 333 | NULL | NULL | NULL |
-------------------------------------------------------
9 rows in set (0.00 sec)mysql stop replica;
Query OK, 0 rows affected (0.07 sec)
# 如果需要一次跳过多条找出需要跳过的gtid批量执行
mysql SET SESSION.GTID_NEXT d58e6bad-ef3e-11ee-8285-0242ac120003:12;begin;commit;
Query OK, 0 rows affected (0.00 sec)Query OK, 0 rows affected (0.00 sec)Query OK, 0 rows affected (0.12 sec)mysql SET SESSION.GTID_NEXT d58e6bad-ef3e-11ee-8285-0242ac120003:13;begin;commit;
Query OK, 0 rows affected (0.00 sec)Query OK, 0 rows affected (0.00 sec)Query OK, 0 rows affected (0.00 sec)mysql SET SESSION GTID_NEXT AUTOMATIC;
Query OK, 0 rows affected (0.00 sec)mysql start replica;
Query OK, 0 rows affected (1.10 sec)mysql select * from user;
-------------------------------------------------------
| id | name | address | last_updated | is_deleted |
-------------------------------------------------------
| 2 | 张三 | 广州白云山 | 1691563465 | 0 |
| 3 | fox | NULL | NULL | NULL |
| 4 | 李四 | NULL | NULL | NULL |
| 5 | 111 | NULL | NULL | NULL |
| 14 | AAA | NULL | NULL | NULL |
| 15 | BBB | NULL | NULL | NULL |
| 16 | CCC | NULL | NULL | NULL |
| 23 | 333 | NULL | NULL | NULL |
-------------------------------------------------------
8 rows in set (0.01 sec)
二、组复制Group Replication 文档https://dev.mysql.com/doc/refman/8.0/en/group-replication.html 1、什么是组复制
由于传统异步复制的缺陷可能会导致主从数据不一致的问题在主节点异常宕机时从节点可能造成数据丢失。基于这个缺陷Mysql5.7.17推出了一个高可用与高扩展的解决方案Mysql Group Replication(简称MGR)将原有的gtid复制功能进行了增强支持单主模式和多主模式。组复制在数据库层面上做到了只要集群中大多数主机可用则服务可用也就是说3台服务器的集群允许其中1台宕机。 Group Replication提供了分布式状态机复制服务器之间具有很强的协调性。当服务器属于同一组时它们会自动进行协调。该组可以在具有自动选主的单主模式下运行在这种模式下一次只有一台服务器接受更新。或者对于更高级的用户可以在多主模式下部署该组其中所有服务器都可以接受更新即使它们是并发执行的。
与传统复制相比Group Replication有以下大幅改进 传统复制的主从复制方式有一个主和不等数量的从。主节点执行的事务会异步发送给从节点在从节点重新执行。而Group Replication采用整组写入的方式避免了单点争用。 Group Replication在传输数据时使用了Paxos协议。Paxos协议保证了数据传输的一致性和原子性。基于Paxos协议Group Replication构建了一个分布式的状态复制机制这是实现多主复制的核心技术。 Group Replication提供了多写方案为多活方案带来了实现的可能。
MGR 能保证数据库服务的连续可用却无法处理如下问题当一个组成员变为不可用时连接到它的客户端必须被重定向或故障转移到其他组成员。此时需要使用连接器、负载均衡器、路由器或某种形式的中间件例如 MySQL Router 8.0 。MGR 本身不提供这些工具。此时便引入了 InnoDB Cluster 后面详述。
2、单主模式
组中的每个MySQL服务器实例都可以在独立的物理主机上运行这是部署组复制的推荐方式。
在单主模式下(group_replication_single_primary_modeON)组中只有一个主服务器该主服务器被设置为读写模式。组中的所有其他成员都被设置为只读模式(super_read_onlyON)。 查找primary的两种方式
# 方式1查询performance_schema.replication_group_members的MEMBER_ROLE列
mysql SELECT MEMBER_HOST, MEMBER_ROLE FROM performance_schema.replication_group_members;
--------------------------------------
| MEMBER_HOST | MEMBER_ROLE |
--------------------------------------
| remote1.example.com | PRIMARY |
| remote2.example.com | SECONDARY |
| remote3.example.com | SECONDARY |
--------------------------------------# 方式2查看group_replication_primary_member变量状态
mysql SHOW STATUS LIKE group_replication_primary_member;2.1、单主模式部署示例 文档https://dev.mysql.com/doc/refman/8.0/en/group-replication-configuring-instances.html 1部署三个MySQL Server实例
可以利用docker快速部署3个MySQL实例
角色server_idDB Port内部通信mgr-node1(primary)133213306mgr-node1:33061mgr-node2(Secondary)233223306mgr-node2:33061mgr-node3(Secondary)333233306mgr-node3:33061
# 创建组复制的网络 保证三个mysql容器之间可以通过容器名访问
docker network create --driver bridge mgr-network
mkdir -p /mysql/mgr/node1/data /mysql/mgr/node1/conf /mysql/mgr/node1/log
mkdir -p /mysql/mgr/node2/data /mysql/mgr/node2/conf /mysql/mgr/node2/log
mkdir -p /mysql/mgr/node3/data /mysql/mgr/node3/conf /mysql/mgr/node3/log#运行mysql容器
docker run -d \
--name mgr-node1 \
--privilegedtrue \
--restartalways \
--network mgr-network \
-p 3321:3306 \
-v /mysql/mgr/node1/data:/var/lib/mysql \
-v /mysql/mgr/node1/conf:/etc/mysql/conf.d \
-v /mysql/mgr/node1/log:/logs \
-e MYSQL_ROOT_PASSWORD123456 \
-e TZAsia/Shanghai mysql:8.0.27 \
--lower_case_table_names1 docker run -d \
--name mgr-node2 \
--privilegedtrue \
--restartalways \
--network mgr-network \
-p 3322:3306 \
-v /mysql/mgr/node2/data:/var/lib/mysql \
-v /mysql/mgr/node2/conf:/etc/mysql/conf.d \
-v /mysql/mgr/node2/log:/logs \
-e MYSQL_ROOT_PASSWORD123456 \
-e TZAsia/Shanghai mysql:8.0.27 \
--lower_case_table_names1 docker run -d \
--name mgr-node3 \
--privilegedtrue \
--restartalways \
--network mgr-network \
-p 3323:3306 \
-v /mysql/mgr/node3/data:/var/lib/mysql \
-v /mysql/mgr/node3/conf:/etc/mysql/conf.d \
-v /mysql/mgr/node3/log:/logs \
-e MYSQL_ROOT_PASSWORD123456 \
-e TZAsia/Shanghai mysql:8.0.27 \
--lower_case_table_names1 2配置组复制实例
以mgr-node1配置为例创建/mysql/mgr/node1/conf/custom.cnf添加以下配置
[mysql]
# 设置mysql客户端默认编码
default-character-setutf8[mysqld]
pid-file /var/run/mysqld/mysqld.pid
socket /var/run/mysqld/mysqld.sock
datadir /var/lib/mysqlsecure-file-priv NULL# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links0#对于Group Replication数据必须存储在InnoDB事务存储引擎中
disabled_storage_enginesMyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY#指定sever_id三个Mysql实例需要分别改为对应的sever_id
server_id1
# 必须开启GTID支持
gtid_modeON
enforce_gtid_consistencyON# 启用二进制日志
log-binmysql-bin#组复制设置
#实例启动时会将组复制插件加载到插件列表中
plugin_load_addgroup_replication.so
# 组名三个节点必须保证一致必须是UUID可以使用 SELECT UUID()生成一个
group_replication_group_name117dc7ea-b9bd-11ee-9bdb-0242ac120002
# 插件在服务器启动时不自动启动可以等配置好服务器之后手动启动
group_replication_start_on_bootoff
# 配置与组内其他成员通信是使用的主机名和端口,内部通讯端口推荐使用 33061
group_replication_local_address mgr-node1:33061
# 设置组成员的主机名和端口
group_replication_group_seeds mgr-node1:33061,mgr-node2:33061,mgr-node3:33061
# 通常会在实例运行时配置group_replication_bootstrap_group以确保只有一个成员实际引导组
group_replication_bootstrap_groupoff# 最大连接数
max_connections1000# 设置默认时区
default-time_zone8:00# 0:区分大小写
# 1:不区分大小写
lower_case_table_names1!includedir /etc/mysql/conf.d/mgr-node2和mgr-node3同上注意配置文件路径和修改server_id和group_replication_local_address 3配置用于分布式恢复的用户凭证
mgr-node1上配置
3.1重新启动mysql实例
docker restart mgr-node1 mgr-node2 mgr-node33.2禁用二进制日志记录以便在每个实例上分别创建复制用户
# mgr-node1为例
[root192-168-65-185 ~]# docker exec -it mgr-node1 /bin/bash
root0955d5f390c6:/# mysql -uroot -p123456
mysql SET SQL_LOG_BIN0;3.3创建MySQL用户,授予所需的权限
mysql CREATE USER fox% IDENTIFIED BY 123456;GRANT REPLICATION SLAVE ON *.* TO fox%;GRANT CONNECTION_ADMIN ON *.* TO fox%;GRANT BACKUP_ADMIN ON *.* TO fox%;GRANT GROUP_REPLICATION_STREAM ON *.* TO fox%;FLUSH PRIVILEGES;3.4如果前面禁用了二进制日志再次启用二进制日志
mysql SET SQL_LOG_BIN1;3.5创建复制用户后必须向服务器提供用于分布式恢复的用户凭据。 使用CHANGE REPLICATION SOURCE TO | CHANGE MASTER TO设置的用户凭据以明文形式存储在服务器上的复制元数据存储库中。当组复制启动时它们将被应用包括当系统变量group_replication_start_on_boot设置为ON时自动启动。 在START GROUP_REPLICATION上指定的用户凭据仅保存在内存中并通过STOP GROUP_REPLICATION语句或服务器关闭来删除。必须发出START GROUP_REPLICATION语句来再次提供凭据因此无法使用这些凭据自动启动Group Replication。这种指定用户凭据的方法有助于保护组复制服务器免受未经授权的访问。此功能从MySQL 8.0.21开始支持。
#from MySQL 8.0.23:
mysql CHANGE REPLICATION SOURCE TO SOURCE_USERfox, SOURCE_PASSWORD123456 FOR CHANNEL group_replication_recovery;注意如果不想配置ssl可以配置参数group_replication_recovery_public_key_pathON来在请求复制用户密钥时给公钥
#实例加入集群需要获取公钥
set global group_replication_recovery_get_public_keyon;4指定mgr-node1引导组primary节点启用组复制
为了安全地引导组连接到mgr-node1并执行以下语句
#mgr-node1启动组复制并且作为primary
mysql SET GLOBAL group_replication_bootstrap_groupON;START GROUP_REPLICATION;SET GLOBAL group_replication_bootstrap_groupOFF;
# 查询组成员信息mgr-node1是否是primary
mysql SELECT MEMBER_HOST, MEMBER_ROLE FROM performance_schema.replication_group_members; 为了验证后续其他节点入组情况下面将创建一个表并向其中添加一些数据进行验证。
CREATE DATABASE IF NOT EXISTS test;
USE test;
CREATE TABLE t1 (c1 INT PRIMARY KEY, c2 TEXT NOT NULL);
INSERT INTO t1 VALUES (1, Fox);5向组中添加实例mgr-node2和mgr-node3
#添加复制用户
SET SQL_LOG_BIN0;
CREATE USER fox% IDENTIFIED BY 123456;
GRANT REPLICATION SLAVE ON *.* TO fox%;
GRANT CONNECTION_ADMIN ON *.* TO fox%;
GRANT BACKUP_ADMIN ON *.* TO fox%;
GRANT GROUP_REPLICATION_STREAM ON *.* TO fox%;
FLUSH PRIVILEGES;
SET SQL_LOG_BIN1;
CHANGE REPLICATION SOURCE TO SOURCE_USERfox, SOURCE_PASSWORD123456 FOR CHANNEL group_replication_recovery;
set global group_replication_recovery_get_public_keyon;# mgr-node2和mgr-node3启用主复制
mysql START GROUP_REPLICATION;
# 查询组成员信息
mysql SELECT MEMBER_HOST, MEMBER_ROLE FROM performance_schema.replication_group_members;确认数据同步情况
SELECT * FROM test.user;如果数据没有正常同步可以通过docker log -f mgr-node2排查问题
3、多主模式 文档https://dev.mysql.com/doc/refman/8.0/en/group-replication-multi-primary-mode.html 在多主模式下(group_replication_single_primary_modeOFF)没有成员具有特殊的角色。任何与其他组成员兼容的成员在加入组时都被设置为读写模式并且可以处理写事务即使它们是并发发布的。
如果一个成员停止接受写事务例如在服务器意外退出的情况下连接到它的客户端可以被重定向或故障转移到处于读写模式的任何其他成员。Group Replication本身不处理客户端故障转移因此需要使用中间件框架(如MySQL Router 8.0)、代理、连接器或应用程序本身来安排。 3.1、多主模式部署示例
在前面单主模式基础上改为多主模式
1三个节点都关闭单主模式
三个节点都执行如下操作
# 停止组复制
stop GROUP_REPLICATION;# 关闭单主模式
set global group_replication_single_primary_modeoff; # 开启多主一致性检查
set global group_replication_enforce_update_everywhere_checksON; 2选择mgr-node1引导组复制
# 开启组复制引导
set global group_replication_bootstrap_groupon;
# 开启组复制
start group_replication; # 关闭组复制引导
set global group_replication_bootstrap_groupoff; 3mgr-node2和mgr-node3开启组复制
# 开启组复制
start group_replication; # 查看到添加到组复制集群的服务器信息
select * from performance_schema.replication_group_members;4测试
mgr-node1插入数据看mgr-node2是否可以查到
#mgr-node1
INSERT INTO test.t1 VALUES (2, aaa);
#mgr-node2
select * from test.t1;