MySQL 8.0 主从复制原理分析与实战
-
- [📋 知识体系总览](#📋 知识体系总览)
- 一、复制(Replication)基础
-
- [✅1. 什么是复制](#✅1. 什么是复制)
- [✅2. 复制的优势与缺点](#✅2. 复制的优势与缺点)
- [✅3. 应用场景](#✅3. 应用场景)
- 二、复制的方式
-
- [✅1. 异步复制](#✅1. 异步复制)
- [✅2. 半同步复制](#✅2. 半同步复制)
- 三、设计理念:复制状态机
- 四、基于binlog位点同步的主从复制原理
-
- [✅1. 复制原理(7步流程)](#✅1. 复制原理(7步流程))
- [✅2. 异步复制实战](#✅2. 异步复制实战)
-
- 1)主节点配置
- 2)从节点1配置
- 3)从节点2配置
- 4)主库-配置复制用户
- 5)从节点-设置主库信息
- [6) 开启从库](#6) 开启从库)
- [7) 测试主从复制功能](#7) 测试主从复制功能)
- [✅3. 半同步复制实战](#✅3. 半同步复制实战)
- [📊 基于binlog位点复制的痛点](#📊 基于binlog位点复制的痛点)
- 五、基于全局事务标识符(GTID)的复制
-
- [✅1. GTID概念与结构](#✅1. GTID概念与结构)
- [✅2. GTID工作原理](#✅2. GTID工作原理)
- [✅3. GTID和位点同步区别](#✅3. GTID和位点同步区别)
- [✅4. GTID配置](#✅4. GTID配置)
- [✅5. GTID主从复制实战](#✅5. GTID主从复制实战)
- [✅6. 主从切换演练](#✅6. 主从切换演练)
- [六、组复制(Group Replication, MGR)](#六、组复制(Group Replication, MGR))
-
- [✅1. 什么是组复制](#✅1. 什么是组复制)
- [✅2. 单主模式部署](#✅2. 单主模式部署)
- [✅3. 多主模式部署](#✅3. 多主模式部署)
- [📋 全文总结](#📋 全文总结)
-
- [✅1. 复制方案演进路线](#✅1. 复制方案演进路线)
- [✅2. 核心面试要点](#✅2. 核心面试要点)
- [✅3. 关键命令速查](#✅3. 关键命令速查)

📋 知识体系总览
MySQL 8.0 主从复制原理分析与实战
├── 一、复制(Replication)基础
│ ├── ✅1. 什么是复制
│ ├── ✅2. 复制的优势与缺点
│ └── ✅3. 应用场景
├── 二、复制的方式与数据同步类型
│ ├── ✅1. 基于binlog位点的复制
│ ├── ✅2. 基于GTID的复制
│ ├── ✅3. 异步复制
│ └── ✅4. 半同步复制
├── 三、设计理念:复制状态机
├── 四、基于binlog位点同步的主从复制原理与实战
│ ├── ✅1. 复制原理(7步流程)
│ ├── ✅2. Docker搭建一主两从实战
│ └── ✅3. 半同步复制实战
├── 五、基于GTID的主从复制
│ ├── ✅1. GTID概念与结构
│ ├── ✅2. GTID工作原理
│ ├── ✅3. GTID配置与实战
│ └── ✅4. 主从切换演练
├── 六、组复制(Group Replication)
│ ├── ✅1. 什么是组复制
│ ├── ✅2. 单主模式部署
│ └── ✅3. 多主模式部署
└── 📋 全文总结
一、复制(Replication)基础
✅1. 什么是复制
MySQL Replication是官方提供的主从同步方案,也是用的最广的同步方案。**Replication(复制)使来自一个 MySQL数据库服务器(称为源(Source))的数据能够复制到一个或多个 MySQL 服务器(称为副本(Replica))。**默认情况下,复制是异步的;副本不需要永久连接即可从源接收更新。根据配置,您可以复制所有数据库、指定数据库,甚至某个数据库中的指定表。
📝 注意: 旧版本的 MySQL 复制将源(Source)称为主(Master),将副本(Replica)称为从(Slave)。

✅2. 复制的优势与缺点
优势:
- 高可用:通过配置一定的复制机制,MySQL 实现了跨主机的数据复制,从而获得一定的高可用能力,如果需要获得更高的可用性,只需要配置多个副本,或者进行级联复制就可以达到目的。
- 性能扩展:由于复制机制提供了多个数据备份,可以通过配置一个或多个副本,将读请求分发至副本节点,从而获得整体上读写性能的提升。
- 异地灾备:只需要将副本节点部署到异地机房,就可以轻松获得一定的异地灾备能力。实际当中,需要考虑网络延迟等可能影响整体表现的因素。
- 交易分离:通过配置复制机制,并将低频、大运算量的交易发送至副本节点执行,就可以避免这些交易与高频交易竞争运算资源,从而避免整体的性能问题。
缺点:
- 没有故障自动转移,容易造成单点故障
- 主库从库之间有主从复制延迟问题,容易造成最终数据的不一致
- 从库过多对主库的负载以及网络带宽都会带来很大的负担
✅3. 应用场景
- 电子商务平台: 主从复制可以用于实现读写分离,提高并发处理能力,同时确保数据的一致性。
- 社交网络: 可以利用主从复制来提供快速的读取服务,同时将数据变更复制到从数据库以备份数据。
- 实时监控和报警系统: 主从复制可以用于实现数据的分布式存储和快速数据查询。
- 新闻和媒体网站: 在高访问量的新闻网站中,可以使用主从复制来提供高可用性和快速的内容访问。
- 金融服务: 数据的安全性和可用性至关重要,主从复制可以用于数据备份和高可用性的实现。
二、复制的方式
MySQL 8.0支持多种复制方式:
① 基于binlog位点的传统复制
基于源的二进制日志(binlog)复制事件,并要求日志文件及其中的位置在源和副本之间进行同步。作为源的 MySQL 实例将更新和更改作为"事件"写入二进制日志。副本配置为从源中读取二进制日志,并在副本的本地数据库上执行二进制日志中的事件。
sql
-- 获取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)的方式。基于 GTID 的复制是完全基于事务的,所以很容易确定源和副本是否一致;只要在源上提交的所有事务也在副本上提交,就可以保证两者之间的一致性。
官网:https://dev.mysql.com/doc/refman/8.0/en/replication-gtids.html
✅1. 异步复制
默认情况下,MySQL 采用异步复制的方式,执行事务操作的线程不会等复制 Binlog 的线程。具体的时序你可以看下面这个图:

MySQL 主库在收到客户端提交事务的请求之后,会先写入 Binlog,然后再提交事务,更新存储引擎中的数据,事务提交完成后,给客户端返回操作成功的响应。同时,从库会有一个专门的复制线程,从主库接收 Binlog,然后把 Binlog 写到一个中继日志里面,再给主库返回复制成功的响应。从库还有另外一个回放 Binlog 的线程,去读中继日志,然后回放 Binlog 更新存储引擎中的数据。
提交事务和复制这两个流程在不同的线程中执行,互相不会等待,这是异步复制。异步复制的劣势是,可能存在主从延迟,如果主节点宕机,可能会丢数据。
✅2. 半同步复制
MySQL 从 5.7 版本开始,增加一种半同步复制(Semisynchronous Replication)的方式。这种机制与异步复制相比主要有如下区别:

可以看出,相比于异步复制,半同步复制在一定程度上提高了数据的可用性,在未退化至异步复制时,如果主节点宕机,此时数据已复制至至少一台从节点。同时,由于向客户端响应时需要从节点完成响应,相比于异步复制,此时多出了主从节点上网络交互的耗时以及从节点写文件并刷盘的耗时,因此整体上集群对于客户端的响应性能表现必然有所降低。
半同步复制有两个重要的参数:
- rpl_semi_sync_master_wait_slave_count(8.0.26之后改为rpl_semi_sync_source_wait_for_replica_count):至少等待数据复制到几个从节点再返回。这个数量配置的越大,丢数据的风险越小,但是集群的性能和可用性就越差。
- rpl_semi_sync_master_wait_point(8.0.26之后改为rpl_semi_sync_source_wait_point):这个参数控制主库执行事务的线程,是在提交事务之前(AFTER_SYNC)等待复制,还是在提交事务之后(AFTER_COMMIT)等待复制。默认是 AFTER_SYNC,也就是先等待复制,再提交事务,这样就不会丢数据。
三、设计理念:复制状态机
在 MySQL 中,无论是复制还是备份恢复,依赖的都是全量备份和 Binlog,全量备份相当于备份那一时刻的一个数据快照,Binlog 则记录了每次数据更新的变化,也就是操作日志。这种基于"快照 + 操作日志"的方法,不是 MySQL 特有的。比如说,Redis Cluster 中,它的全量备份称为 Snapshot,操作日志叫 backlog,它的主从复制方式几乎和 MySQL 是一模一样的。Elasticsearch用的是 translog,它备份和恢复数据的原理和实现方式也是完全一样的。
任何一个存储系统,无论它存储的是什么数据,用什么样的数据结构,都可以抽象成一个状态机。存储系统中的数据称为状态(也就是 MySQL 中的数据),状态的全量备份称为快照(Snapshot),就像给数据拍个照片一样。我们按照顺序记录更新存储系统的每条操作命令,就是操作日志(Commit Log,也就是 MySQL 中的 Binlog)。

复制数据的时候,只要基于一个快照,按照顺序执行快照之后的所有操作日志,就可以得到一个完全一样的状态。在从节点持续地从主节点上复制操作日志并执行,就可以让从节点上的状态数据和主节点保持同步。
主从同步做数据复制时,一般可以采用几种复制策略。
- 性能最好的方法是异步复制,主节点上先记录操作日志,再更新状态数据,然后异步把操作日志复制到所有从节点上,并在从节点执行操作日志,得到和主节点相同的状态数据。异步复制的劣势是,可能存在主从延迟,如果主节点宕机,可能会丢数据。
- 另外一种常用的策略是半同步复制,主节点等待操作日志最少成功复制到 N 个从节点上之后,再更新状态,这种方式在性能、高可用和数据可靠性几个方面都比较平衡,很多分布式存储系统默认采用的都是这种方式。
四、基于binlog位点同步的主从复制原理
✅1. 复制原理(7步流程)

- 主库会生成多个 binlog 日志文件
- 从库的 I/O 线程请求指定文件和指定位置的 binlog 日志文件(位点)
- 主库 dump 线程获取指定位点的 binlog 日志
- 主库按照从库发送给来的位点信息读取 binlog,然后推送 binlog 给从库
- 从库将得到的 binlog 写到本地的 relay log (中继日志) 文件中
- 从库的 SQL 线程读取和解析 relay log 文件
- 从库的 SQL 线程重放 relay log 中的命令
✅2. 异步复制实战
架构规划:
| 角色 | server_id | ip:port |
|---|---|---|
| mysql-source (主) | 10 | 192.168.65.185:3307 |
| mysql-replica1 (从1) | 11 | 192.168.65.185:3308 |
| mysql-replica2 (从2) | 12 | 192.168.65.185:3309 |
1)主节点配置
1.创建挂载目录
bash
mkdir -p /mysql/replication/source/data /mysql/replication/source/conf /mysql/replication/source/log
2.准备配置文件(server-id=11)
vim /mysql/replication/source/conf/custom.cnf
ini
[mysql]
# 设置mysql客户端默认编码
default-character-set=utf8
[mysqld]
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
datadir = /var/lib/mysql
secure-file-priv= NULL
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
# 服务器唯一ID,默认是1
server-id=10
# 启用二进制日志
log-bin=mysql-bin
# 最大连接数
max_connections=1000
# 设置默认时区
default-time_zone='+8:00'
# 0:区分大小写
# 1:不区分大小写
lower_case_table_names=1
!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: 如果设置为0,MySQL服务器将不允许在数据目录中使用符号链接。这有助于防止安全风险。
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:不同步的数据库日志
📝 关键参数说明:
server-id:每个MySQL服务器实例在复制时需要有一个唯一的IDlog-bin:启用二进制日志,记录所有对数据库的更改,复制和恢复的必要条件replicate_do_db:待同步的数据库日志replicate_ignore_db:不同步的数据库日志
3.运行mysql容器
bash
# 创建主从复制的网络
docker network create --driver bridge mysql-source-replica
# 运行mysql容器
docker run -d \
--name mysql-source \
--privileged=true \
--restart=always \
--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_PASSWORD=123456 \
-e TZ=Asia/Shanghai mysql:8.0.27 \
--lower_case_table_names=1
可以查询启动情况:
bash
docker logs mysql-source -f
4.配置远程访问
bash
docker exec -it mysql-source /bin/bash
mysql -u root -p
sql
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '123456';
flush privileges;
2)从节点1配置
1.创建挂载目录
bash
mkdir -p /mysql/replication/replica1/data /mysql/replication/replica1/conf /mysql/replication/replica1/log
2.准备配置文件(server-id=11)
bash
vim /mysql/replication/replica1/conf/custom.cnf
bash
[mysql]
# 设置mysql客户端默认编码
default-character-set=utf8
[mysqld]
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
datadir = /var/lib/mysql
secure-file-priv= NULL
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
# 服务器唯一ID,默认是1
server-id=11
# 启用二进制日志
log-bin=mysql-bin
# 最大连接数
max_connections=1000
# 设置默认时区
default-time_zone='+8:00'
# 0:区分大小写
# 1:不区分大小写
lower_case_table_names=1
!includedir /etc/mysql/conf.d/
- 运行mysql容器
bash
docker run -d \
--name mysql-replica1 \
--privileged=true \
--restart=always \
--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_PASSWORD=123456 \
-e TZ=Asia/Shanghai mysql:8.0.27 \
--lower_case_table_names=1
- 配置远程访问
bash
docker exec -it mysql-replica1 /bin/bash
mysql -u root -p
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '123456';
flush privileges;
3)从节点2配置
1.创建挂载目录
bash
mkdir -p /mysql/replication/replica2/data /mysql/replication/replica2/conf /mysql/replication/replica2/log
2.准备配置文件(server-id=11)
bash
vim /mysql/replication/replica2/conf/custom.cnf
bash
[mysql]
# 设置mysql客户端默认编码
default-character-set=utf8
[mysqld]
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
datadir = /var/lib/mysql
secure-file-priv= NULL
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
# 服务器唯一ID,默认是1
server-id=12
# 启用二进制日志
log-bin=mysql-bin
# 最大连接数
max_connections=1000
# 设置默认时区
default-time_zone='+8:00'
# 0:区分大小写
# 1:不区分大小写
lower_case_table_names=1
!includedir /etc/mysql/conf.d/
- 运行mysql容器
bash
docker run -d \
--name mysql-replica2 \
--privileged=true \
--restart=always \
--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_PASSWORD=123456 \
-e TZ=Asia/Shanghai mysql:8.0.27 \
--lower_case_table_names=1
- 配置远程访问
bash
docker exec -it mysql-replica2 /bin/bash
mysql -u root -p
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '123456';
flush privileges;
4)主库-配置复制用户
每个副本使用一个 MySQL 用户名和密码连接到源,因此在源上必须有一个用户帐户,副本可以使用该帐户进行连接。
sql
-- 连接主库mysql-source
CREATE USER 'fox'@'%' IDENTIFIED WITH mysql_native_password BY '123456';
GRANT REPLICATION SLAVE ON *.* TO 'fox'@'%';
flush privileges;
查看master状态
sql
-- 主库上执行
SHOW MASTER STATUS;
"File"列显示日志文件的名称,"Position"列显示文件内的位置。

5)从节点-设置主库信息
在从库上执行 CHANGE REPLICATION SOURCE TO 语句(MySQL 8.0.23+)或 CHANGE MASTER TO 语句(MySQL 8.0.23之前):
sql
-- MySQL 8.0.23之前
CHANGE MASTER TO
MASTER_HOST='source_host_name',
MASTER_USER='replication_user_name',
MASTER_PASSWORD='replication_password',
MASTER_LOG_FILE='recorded_log_file_name',
MASTER_LOG_POS=recorded_log_position;
-- MySQL 8.0.23+
CHANGE REPLICATION SOURCE TO
SOURCE_HOST='source_host_name',
SOURCE_USER='replication_user_name',
SOURCE_PASSWORD='replication_password',
SOURCE_LOG_FILE='recorded_log_file_name',
SOURCE_LOG_POS=recorded_log_position;
从库1、2执行:
from MySQL 8.0.23 执行下面的命令。
sql
change replication source to
source_host='192.168.80.3',
source_user='fox',
source_password='123456',
source_port=3307,
source_log_file='mysql-bin.000003',
source_log_pos=1273,
source_connect_retry=30;
source_host:主数据库的IP地址;
source_port:主数据库的运行端口;
source_user:在主数据库创建的用于同步数据的用户账号;
source_password:在主数据库创建的用于同步数据的用户密码;
source_log_file:指定从数据库要复制数据的日志文件,通过查看主数据的状态,获取File参数;
source_log_pos:指定从数据库从哪个位置开始复制数据,通过查看主数据的状态,获取Position参数;
source_connect_retry:连接失败重试的时间间隔,单位为秒。

6) 开启从库
在mysql命令行执行。
sql
-- 开启从库
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) 测试主从复制功能
sql
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
CREATE DATABASE IF NOT EXISTS test;
USE test;
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;
INSERT INTO `user` VALUES (2, '张三', '广州白云山', 1691563465, 0);
SET FOREIGN_KEY_CHECKS = 1;
在主库执行后,从库都有了则成功了
✅3. 半同步复制实战
文档:https://dev.mysql.com/doc/refman/8.0/en/replication-semisync-installation.html
1)安装半同步插件
主节点:
sql
-- MySQL 8.0.26+
INSTALL PLUGIN rpl_semi_sync_source SONAME 'semisync_source.so';
-- 验证是否成功安装
SELECT PLUGIN_NAME, PLUGIN_STATUS
FROM INFORMATION_SCHEMA.PLUGINS
WHERE PLUGIN_NAME LIKE '%semi%';

从节点:
sql
-- MySQL 8.0.26+
INSTALL PLUGIN rpl_semi_sync_replica SONAME 'semisync_replica.so';
-- 验证
SELECT PLUGIN_NAME, PLUGIN_STATUS
FROM INFORMATION_SCHEMA.PLUGINS
WHERE PLUGIN_NAME LIKE '%semi%';

2)开启半同步功能
主节点:
sql
SET GLOBAL rpl_semi_sync_source_enabled=1;
show variables like "%semi_sync%";

从节点:
sql
set global rpl_semi_sync_replica_enabled=1;
show variables like "%semi_sync%";

3)重启从节点I/O线程
sql
STOP REPLICA IO_THREAD;
START REPLICA IO_THREAD;
4)半同步复制测试
**测试:**当从节点响应超时时,主节点会将同步机制退化为异步复制。 从节点恢复后,同步机制是否会恢复为半同步复制
sql
-- 修改主节点半同步属性
set global rpl_semi_sync_source_wait_for_replica_count=2;
set global rpl_semi_sync_source_timeout=100000;
-- 停掉从节点2
-- (在宿主机执行) docker stop mysql-replica2
-- 恢复从节点2
-- docker start mysql-replica2
-- 从节点2中执行
set global rpl_semi_sync_replica_enabled=1;
STOP REPLICA IO_THREAD;
START REPLICA IO_THREAD;
📝 测试结论: 当从节点响应超时时,主节点会将同步机制退化为异步复制。从节点恢复后,同步机制会恢复为半同步复制。
📊 基于binlog位点复制的痛点
痛点 1:首次开启主从复制的步骤复杂
- 第一次开启主从同步时,要求从库和主库是一致的。
- 找到主库的 binlog 位点。
- 设置从库的 binlog 位点。
- 开启从库的复制线程。
痛点 2: 恢复主从复制的步骤复杂
- 找到从库复制线程停止时的位点。
- 解决复制异常的事务。无法解决时就需要手动跳过指定类型的错误,比如通过设置 slave_skip_errors=1032,1062。当然这个前提条件是跳过这类错误是无损的。(1062 错误是插入数据时唯一键冲突;1032 错误是删除数据时找不到行)
不论是首次开启同步时需要找位点和设置位点,还是恢复主从复制时,设置位点和忽略错误,这些步骤都显得过于复杂,而且容易出错。所以 MySQL 5.6 版本引入了 GTID,彻底解决了这个困难。
| 痛点 | 描述 |
|---|---|
| 痛点1:首次开启步骤复杂 | 要求从库和主库一致 → 找到主库binlog位点 → 设置从库binlog位点 → 开启复制线程 |
| 痛点2:恢复步骤复杂 | 找到从库停止时的位点 → 解决复制异常事务 → 手动跳过错误(如设置 slave_skip_errors=1032,1062) |
📝 关键理解: 1062错误是插入数据时唯一键冲突;1032错误是删除数据时找不到行。MySQL 5.6 版本引入GTID彻底解决了这些问题。
五、基于全局事务标识符(GTID)的复制
✅1. GTID概念与结构
官网:https://dev.mysql.com/doc/refman/8.0/en/replication-gtids.html
**GTID是一个基于原始MySQL服务器生成的一个已经被成功执行的全局事务ID,它由服务器ID以及事务ID组合而成。**这个全局事务ID在所有存在主从关系的MySQL服务器上也是唯一的。
GTID核心特性:
- 一个GTID在一个服务器上只执行一次,避免重复执行导致数据混乱或者主从不一致。
- GTID用来代替传统复制方法,不再使用
MASTER_LOG_FILE + MASTER_LOG_POS开启复制,而是使用MASTER_AUTO_POSITION=1。 - 在GTID中replica端的binlog必须开启,目的是记录执行过的GTID(强制)。
GTID结构:
GTID = source_id:transaction_id
source_id:标识源服务器,即源服务器唯一的server_uuid,由于GTID会传递到replica,所以也可以理解为源IDtransaction_id:是一个序列号,由事务在源上提交的顺序决定,序列号的上限是有符号64位整数(2^63-1)
示例:
3E11FA47-71CA-11E1-9E33-C80AA9429562:23
GTID集合:
来自同一服务器的一系列GTID可以折叠成单个表达式:
3E11FA47-71CA-11E1-9E33-C80AA9429562:1-5
多个单一GTID或GTID范围也可以包含在单个表达式中:
3E11FA47-71CA-11E1-9E33-C80AA9429562:1-3:11:47-49
来自不同服务器的GTID集合:
2174B383-5441-11E8-B90A-C80AA9429562:1-3, 24DA167-0C0C-11E8-8442-00059A3C7B00:1-19
📝 注意: GTID存储在mysql数据库中名为gtid_executed的表中。该表中的一行包含它所代表的每个GTID或GTID集合的起始服务器的UUID,以及该集合的开始和结束事务id。

✅2. GTID工作原理
主库计算主库GTID集合和从库GTID集合的差集,主库推送差集binlog给从库。

从库同步逻辑:
- 从库B指定主库A,基于主备协议建立连接
- 从库B把集合y发给主库A
- 主库A计算出集合x和集合y的差集 (集合x中存在,集合y中不存在的GTID集合)。比如集合x是1100,集合y是190,差集就是91~100。这里会判断集合x是否包含集合y的所有GTID,如果不是则说明主库A删除了从库B需要的binlog,主库A直接返回错误
- 主库A从自己的binlog文件里面,找到第一个不在集合y中的事务GTID
- 主库A从该GTID开始,往后读binlog文件,按顺序取binlog发给B
- 从库B的I/O线程读取binlog生成relay log,SQL线程解析relay log执行SQL语句
✅3. GTID和位点同步区别
- **位点同步方案是通过人工在从库上指定哪个位点,**主库就发哪个位点,不做日志的完整性判断。
- **而 GTID 方案是通过主库来自动计算位点的,**不需要人工去设置位点,对运维人员友好。
✅4. GTID配置
GTID配置主要做3件事,如下:
1.主库配置:
在配置文件下添加:
ini
#GTID:
# 启用全局事务标识符(GTID)模式
gtid_mode=on
# 强制GTID的一致性。这意味着在执行事务时,MySQL将确保所有涉及的服务器都使用相同的GTID集。
enforce_gtid_consistency=on
2.从库配置(同上):
ini
#GTID:
gtid_mode=on
enforce_gtid_consistency=on
3.从节点设置主库信息(GTID模式):
sql
# 从库配置同步参数
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. GTID主从复制实战
在前面基于binlog日志主从复制的基础上配置GTID:
1)设置全局只读模式:
注意:该步骤只在已经子啊进行主从复制,而不使用gtid的服务器时才需要此步骤。对于新服务器,请继续执行步骤3。
在主从服务器上都执行下面的命令:
sql
# 设置MySQL服务器的全局只读模式
mysql> SET @@GLOBAL.read_only = ON;

2)停止所有服务器:
bash
docker stop mysql-source mysql-replica1 mysql-replica2
3)配置并启用GTID:
修改 custom.cnf,添加GTID配置,然后启动:
vim /mysql/replication/source/conf/custom.cnf
vim /mysql/replication/replica1/conf/custom.cnf
vim /mysql/replication/replica2/conf/custom.cnf
# 启用GTID
gtid_mode=ON
enforce-gtid-consistency=ON
主从节点都启用GTID
bash
docker start mysql-source mysql-replica1 mysql-replica2
4)从节点配置基于GTID的自动定位:
sql
stop replica;
change replication source to
source_host='192.168.80.3',
source_user='fox',
source_password='123456',
source_port=3307,
source_auto_position=1;

5)开启从库复制并禁用只读模式:
sql
start replica;
SET @@GLOBAL.read_only = OFF;
-- 查看状态
show replica status \G

✅6. 主从切换演练
场景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升级为主库
将主库宕机,从库1升级为主库、从库2切换主库为从库1(新的主库),观察从库2是否同步未完成的事务
1)停止主库
bash
docker stop mysql-source
2)设置新主库
设置replica1 为replica2的主库,因为replica1的数据是完整的。
按照普通复制方法,需要计算主库的log_pos和从库设置成主库的log_pos,可能出现错误
因为同一事务的GTID在所有节点上的值一致,那么根据replica2当前停止点的GTID就能定位到要主库的GTID,所以直接在replica2上执行change即可
bash
# 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_host='192.168.80.3',source_port=3308,source_user='fox',source_password='123456',source_auto_position=1;
mysql> start replica;

此时从库1为主库,从库2可以直接从新的主库同步数据
场景3:从库删除表后主库继续插入,复制中断修复
模拟从库删除测试表,主库对表进行插入操作。观察从库复制是否报错
1)replica1删除test.user表,主库插入新记录
sql
-- 从库1删除user表
drop table test.user;
-- 主库插入新记录
INSERT INTO `test`.`user` VALUES (14, 'AAA', NULL, NULL, NULL);
2)查看从库同步情况
bash
# 从库1执行
mysql> show replica status\G
查看从库状态会报错:Worker 1 failed executing transaction。可以看出从库复制中断 (注意:删除了表,无法插入)

报错信息:事务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)复制中断修复: 采用从库跳过错误事务修复
先从主库将表数据拷贝到从库,因为从库user表已经删了(user表中部分数据不是利用gtid复制过去的)
bash
# 1.停止从库1复制进程
mysql> stop replica;
# 2.设置出现错误的事务号,事务号从 Last_Error 获取,在session里设置gtid_next,即跳过这个GTID
# 注意,选择跳过出现错误的事务
mysql> SET @@SESSION.GTID_NEXT= '83fca6d7-7393-11f1-947e-d6901fb01b86:5';
# 3.设置空事物
mysql> BEGIN; COMMIT;
# 4.恢复自增事物号
mysql> SET SESSION GTID_NEXT = AUTOMATIC;
# 5.启动从库1复制进程
mysql> start replica;
# 然后在主库插入新数据,再次查询从库数据已经同步过来了
mysql> select * from test.user;
注意:设置出现错误的事务号,事务号从 Last_Error 获取
批量跳过多个事务:
sql
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;
六、组复制(Group Replication, MGR)
✅1. 什么是组复制
文档:https://dev.mysql.com/doc/refman/8.0/en/group-replication.html
由于传统异步复制的缺陷,可能会导致主从数据不一致的问题,在主节点异常宕机时从节点可能造成数据丢失。基于这个缺陷,Mysql5.7.17推出了一个高可用与高扩展的解决方案Mysql Group Replication(简称MGR),将原有的gtid复制功能进行了增强,支持单主模式和多主模式。组复制在数据库层面上做到了只要集群中大多数主机可用,则服务可用,也就是说3台服务器的集群,允许其中1台宕机。
📝 核心: 组复制在数据库层面上做到了只要集群中大多数主机可用,则服务可用。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 ,后面详述。
与传统复制对比:
| 维度 | 传统复制 | Group Replication |
|---|---|---|
| 写入方式 | 主节点执行事务异步发送给从节点 | 整组写入,避免单点争用 |
| 一致性协议 | 无 | Paxos协议,保证一致性和原子性 |
| 多写支持 | 不支持 | 支持多主模式 |
MGR局限性:
- 当一个组成员变为不可用时,连接到它的客户端必须被重定向或故障转移到其他组成员
- 需要使用连接器、负载均衡器、路由器或中间件(如 MySQL Router 8.0)
- MGR本身不提供这些工具,此时便引入了 InnoDB Cluster
✅2. 单主模式部署
组中的每个MySQL服务器实例都可以在独立的物理主机上运行,这是部署组复制的推荐方式。
在单主模式下(group_replication_single_primary_mode=ON),组中只有一个主服务器,该主服务器被设置为读写模式。组中的所有其他成员都被设置为只读模式(super_read_only=ON)。

查找Primary的两种方式:
sql
-- 方式1:查询表
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:查看变量
SHOW STATUS LIKE 'group_replication_primary_member';
☑️部署步骤
1)部署三个MySQL Server实例:
| 角色 | server_id | DB Port | 内部通信 |
|---|---|---|---|
| mgr-node1 (primary) | 1 | 3321→3306 | mgr-node1:33061 |
| mgr-node2 (Secondary) | 2 | 3322→3306 | mgr-node2:33061 |
| mgr-node3 (Secondary) | 3 | 3323→3306 | mgr-node3:33061 |
bash
# 创建组复制的网络 保证三个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 \
--privileged=true \
--restart=always \
--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_PASSWORD=123456 \
-e TZ=Asia/Shanghai mysql:8.0.27 \
--lower_case_table_names=1
docker run -d \
--name mgr-node2 \
--privileged=true \
--restart=always \
--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_PASSWORD=123456 \
-e TZ=Asia/Shanghai mysql:8.0.27 \
--lower_case_table_names=1
docker run -d \
--name mgr-node3 \
--privileged=true \
--restart=always \
--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_PASSWORD=123456 \
-e TZ=Asia/Shanghai mysql:8.0.27 \
--lower_case_table_names=1
2)配置组复制实例
以mgr-node1配置为例,创建/mysql/mgr/node1/conf/custom.cnf,添加以下配置:
ini
[mysql]
# 设置mysql客户端默认编码
default-character-set=utf8
[mysqld]
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
datadir = /var/lib/mysql
secure-file-priv= NULL
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
#对于Group Replication,数据必须存储在InnoDB事务存储引擎中
disabled_storage_engines="MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY"
#指定sever_id,三个Mysql实例需要分别改为对应的sever_id
server_id=1
# 必须开启GTID支持
gtid_mode=ON
enforce_gtid_consistency=ON
# 启用二进制日志
log-bin=mysql-bin
#组复制设置
#实例启动时会将组复制插件加载到插件列表中
plugin_load_add='group_replication.so'
# 组名三个节点必须保证一致,必须是UUID,可以使用 SELECT UUID()生成一个
group_replication_group_name="117dc7ea-b9bd-11ee-9bdb-0242ac120002"
# 插件在服务器启动时不自动启动,可以等配置好服务器之后手动启动
group_replication_start_on_boot=off
# 配置与组内其他成员通信是使用的主机名和端口,内部通讯端口,推荐使用 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_group=off
# 最大连接数
max_connections=1000
# 设置默认时区
default-time_zone='+8:00'
# 0:区分大小写
# 1:不区分大小写
lower_case_table_names=1
!includedir /etc/mysql/conf.d/
mgr-node2和mgr-node3同上,注意配置文件路径和修改server_id和group_replication_local_address

| 参数 | 说明 |
|---|---|
plugin_load_add='group_replication.so' |
启动时加载组复制插件 |
group_replication_group_name |
组名,三个节点必须一致(UUID格式) |
group_replication_start_on_boot=off |
插件在服务器启动时不自动启动 |
group_replication_local_address |
内部通讯端口,推荐33061 |
group_replication_group_seeds |
设置组成员的主机名和端口 |
group_replication_bootstrap_group=off |
确保只有一个成员实际引导组 |
注意: mgr-node2和mgr-node3的配置需要修改
server_id和group_replication_local_address。
3)配置分布式恢复用户凭证:
sql
-- 重启MySQL实例后连接
docker restart mgr-node1 mgr-node2 mgr-node3
-- 禁用二进制日志,创建复制用户
docker exec -it mgr-node1 /bin/bash
mysql -uroot -p123456
SET SQL_LOG_BIN=0;
-- 创建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;
-- 如果前面禁用了二进制日志,再次启用二进制日志
SET SQL_LOG_BIN=1;
创建复制用户后,必须向服务器提供用于分布式恢复的用户凭据。
-
使用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_USER='fox', SOURCE_PASSWORD='123456' FOR CHANNEL 'group_replication_recovery';
4)指定mgr-node1引导组(Primary节点):
sql
#mgr-node1启动组复制,并且作为primary
mysql> SET GLOBAL group_replication_bootstrap_group=ON;
START GROUP_REPLICATION;
SET GLOBAL group_replication_bootstrap_group=OFF;
# 查询组成员信息,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:
sql
#添加复制用户
SET SQL_LOG_BIN=0;
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_BIN=1;
CHANGE REPLICATION SOURCE TO SOURCE_USER='fox', SOURCE_PASSWORD='123456' FOR CHANNEL 'group_replication_recovery';
set global group_replication_recovery_get_public_key=on;
# mgr-node2和mgr-node3启用主复制
mysql> START GROUP_REPLICATION;
# 查询组成员信息
mysql> SELECT MEMBER_HOST, MEMBER_ROLE FROM performance_schema.replication_group_members;

✅3. 多主模式部署
文档:https://dev.mysql.com/doc/refman/8.0/en/group-replication-multi-primary-mode.html
在多主模式下(group_replication_single_primary_mode=OFF),没有成员具有特殊的角色。任何与其他组成员兼容的成员在加入组时都被设置为读写模式,并且可以处理写事务,即使它们是并发发布的。
如果一个成员停止接受写事务,例如,在服务器意外退出的情况下,连接到它的客户端可以被重定向或故障转移到处于读写模式的任何其他成员。Group Replication本身不处理客户端故障转移,因此需要使用中间件框架(如MySQL Router 8.0)、代理、连接器或应用程序本身来安排。

在前面单主模式基础上改为多主模式
1)三个节点都关闭单主模式
三个节点都执行如下操作
# 停止组复制
stop GROUP_REPLICATION;
# 关闭单主模式
set global group_replication_single_primary_mode=off;
# 开启多主一致性检查
set global group_replication_enforce_update_everywhere_checks=ON;

2)选择mgr-node1引导组复制
# 开启组复制引导
set global group_replication_bootstrap_group=on;
# 开启组复制
start group_replication;
# 关闭组复制引导
set global group_replication_bootstrap_group=off;

3)mgr-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;

📋 全文总结
✅1. 复制方案演进路线
异步复制 → 半同步复制 → GTID复制 → 组复制(MGR) → InnoDB Cluster
| 方案 | 核心特点 | 适用场景 |
|---|---|---|
| 异步复制 | 性能最好,可能丢数据 | 对数据丢失不敏感的场景 |
| 半同步复制 | 至少一个从节点确认后才返回 | 需要一定数据可靠性 |
| GTID复制 | 自动定位,failover简单 | 需要简化运维的场景 |
| 组复制(MGR) | Paxos协议,多主支持,强一致性 | 高可用要求高的场景 |
✅2. 核心面试要点
- 复制的基本原理:基于binlog,I/O线程拉取 → relay log → SQL线程回放
- 异步 vs 半同步:异步不等待从库确认,半同步等待至少一个从库确认
- GTID的核心价值:自动计算位点差集,简化failover,保证一致性
- 组复制的核心:Paxos协议实现分布式状态机复制,支持单主/多主模式
- 位点复制痛点:首次搭建和故障恢复步骤复杂,容易出错
- 半同步的两个关键参数 :
wait_for_replica_count和wait_point(AFTER_SYNC为默认)
✅3. 关键命令速查
sql
-- 查看binlog
SHOW MASTER STATUS;
SHOW BINARY LOGS;
-- 传统复制配置
CHANGE REPLICATION SOURCE TO SOURCE_HOST='...', SOURCE_USER='...',
SOURCE_PASSWORD='...', SOURCE_LOG_FILE='...', SOURCE_LOG_POS=...;
-- GTID复制配置
CHANGE REPLICATION SOURCE TO SOURCE_HOST='...', SOURCE_USER='...',
SOURCE_PASSWORD='...', SOURCE_AUTO_POSITION=1;
-- 控制复制
START REPLICA; / STOP REPLICA;
SHOW REPLICA STATUS \G
-- 跳过GTID错误
SET @@SESSION.GTID_NEXT='uuid:N'; BEGIN; COMMIT;
SET SESSION GTID_NEXT = AUTOMATIC;
-- 组复制
START GROUP_REPLICATION;
SELECT * FROM performance_schema.replication_group_members;
INSERT INTO test.t1 VALUES (2, 'aaa');
#mgr-node2
select * from test.t1;
[外链图片转存中...(img-elgeJLB2-1782916974755)]
## 📋 全文总结
### ✅1. 复制方案演进路线
异步复制 → 半同步复制 → GTID复制 → 组复制(MGR) → InnoDB Cluster
| 方案 | 核心特点 | 适用场景 |
|------|---------|---------|
| 异步复制 | 性能最好,可能丢数据 | 对数据丢失不敏感的场景 |
| 半同步复制 | 至少一个从节点确认后才返回 | 需要一定数据可靠性 |
| GTID复制 | 自动定位,failover简单 | 需要简化运维的场景 |
| 组复制(MGR) | Paxos协议,多主支持,强一致性 | 高可用要求高的场景 |
### ✅2. 核心面试要点
1. **复制的基本原理**:基于binlog,I/O线程拉取 → relay log → SQL线程回放
2. **异步 vs 半同步**:异步不等待从库确认,半同步等待至少一个从库确认
3. **GTID的核心价值**:自动计算位点差集,简化failover,保证一致性
4. **组复制的核心**:Paxos协议实现分布式状态机复制,支持单主/多主模式
5. **位点复制痛点**:首次搭建和故障恢复步骤复杂,容易出错
6. **半同步的两个关键参数**:`wait_for_replica_count` 和 `wait_point`(AFTER_SYNC为默认)
### ✅3. 关键命令速查
```sql
-- 查看binlog
SHOW MASTER STATUS;
SHOW BINARY LOGS;
-- 传统复制配置
CHANGE REPLICATION SOURCE TO SOURCE_HOST='...', SOURCE_USER='...',
SOURCE_PASSWORD='...', SOURCE_LOG_FILE='...', SOURCE_LOG_POS=...;
-- GTID复制配置
CHANGE REPLICATION SOURCE TO SOURCE_HOST='...', SOURCE_USER='...',
SOURCE_PASSWORD='...', SOURCE_AUTO_POSITION=1;
-- 控制复制
START REPLICA; / STOP REPLICA;
SHOW REPLICA STATUS \G
-- 跳过GTID错误
SET @@SESSION.GTID_NEXT='uuid:N'; BEGIN; COMMIT;
SET SESSION GTID_NEXT = AUTOMATIC;
-- 组复制
START GROUP_REPLICATION;
SELECT * FROM performance_schema.replication_group_members;
