MySQL 复制是构建高可用和数据分发系统的基础,两种主要的复制技术---GTID 复制和基于位置的复制---在实现方式和特性上有显著差异。
基于位置的复制(Binlog Position-Based Replication)
基于位置的复制是 MySQL 的传统复制方式,在 MySQL 5.6 之前是唯一的复制方法。
工作原理
sequenceDiagram
participant Master
participant Slave
Master->>Master: 写入事务到二进制日志
Master->>Master: 记录 binlog 文件名和位置
Slave->>Master: 请求从特定文件名和位置开始的二进制日志
Master->>Slave: 传送二进制日志事件
Slave->>Slave: 应用二进制日志事件
Slave->>Slave: 更新 master.info 文件记录复制位置
主要特点
-
坐标标识 :使用二进制日志文件名和位置(如
mysql-bin.000003, position 73
)标识复制点 -
配置复杂性 :需手动指定复制起点,例如:
sqlCHANGE MASTER TO MASTER_HOST='master_host', MASTER_USER='replication_user', MASTER_PASSWORD='replication_password', MASTER_LOG_FILE='mysql-bin.000003', MASTER_LOG_POS=73;
-
故障恢复:当发生主从切换时,需要找出新主服务器与其它从服务器之间的精确二进制日志位置关系
基于 GTID 的复制(Global Transaction ID-Based Replication)
GTID 复制是 MySQL 5.6 版本引入的增强型复制技术,在 5.7 及以上版本得到了进一步完善。
工作原理
sequenceDiagram
participant Master
participant Slave
Master->>Master: 生成唯一的 GTID (源服务器 UUID + 事务序号)
Master->>Master: 写入事务到二进制日志,包含 GTID
Slave->>Master: 告知已执行过的 GTID 集合
Master->>Slave: 发送 Slave 尚未执行的事务
Slave->>Slave: 应用事务并记录 GTID
Slave->>Slave: 更新已执行 GTID 集合
主要特点
-
全局唯一标识 :每个事务都有全局唯一的 GTID,格式为
source_id:transaction_id
- 例如:
3E11FA47-71CA-11E1-9E33-C80AA9429562:23
- 例如:
-
配置简化 :不需要指定日志文件名和位置,只需指定主服务器地址:
sqlCHANGE MASTER TO MASTER_HOST='master_host', MASTER_USER='replication_user', MASTER_PASSWORD='replication_password', MASTER_AUTO_POSITION=1;
-
自动定位:从服务器自动请求它尚未执行的事务
两种复制方式的详细对比
特性 | 基于位置的复制 | 基于 GTID 的复制 |
---|---|---|
可用版本 | 所有版本 | MySQL 5.6 及以上 |
故障转移 | 复杂,需要手动找出各从服务器上的二进制日志位置 | 简单,自动找到正确的复制位置 |
多主拓扑变更 | 难以维护,可能需要重新搭建复制 | 简化了拓扑变更 |
复制点标识 | 基于文件名和位置,相对主观 | 基于唯一 ID,客观且全局唯一 |
事务重复执行 | 可能出现,需要手动解决 | 自动跳过已执行事务 |
事务丢失 | 可能出现,难以检测 | 通过空洞事务检测可减少丢失风险 |
复制过滤 | 支持多种级别的过滤 | 限制更多,某些过滤功能受限 |
配置复杂度 | 较高,需指定精确位置 | 较低,仅需启用自动定位 |
维护成本 | 较高 | 较低 |
兼容性问题 | 较少 | 某些操作有限制(如 CREATE TABLE ... SELECT) |
性能开销 | 略低 | 略高,需维护 GTID 信息 |
可诊断性 | 较难诊断复制问题 | 更容易诊断和修复复制问题 |
技术实现差异
基于位置的复制实现
-
复制坐标记录
- 主服务器记录每个事务在二进制日志中的文件名和位点
- 从服务器在
master.info
文件中记录当前复制位置 - 从服务器在 I/O 线程中记录
master_log_file
和read_master_log_pos
- SQL 线程记录
relay_master_log_file
和exec_master_log_pos
-
复制恢复与故障处理
sql-- 发生故障后,从日志中找出适当位置 CHANGE MASTER TO MASTER_HOST='new_master', MASTER_LOG_FILE='mysql-bin.000089', MASTER_LOG_POS=5670;
GTID 复制实现
-
GTID 生成与事务执行
- 每个服务器有全局唯一的 UUID
- 事务提交前,服务器为事务分配一个序号
- GTID = 服务器 UUID + 序号(如
3E11FA47-71CA-11E1-9E33-C80AA9429562:23
) - GTID 与事务一起写入二进制日志
-
GTID 跟踪机制
- 服务器维护两个 GTID 集合:
gtid_executed
:已执行的事务 GTID 集合gtid_purged
:已执行但二进制日志可能已被清理的 GTID 集合
- 服务器维护两个 GTID 集合:
-
复制控制过程
markdown1. 从服务器连接主服务器时发送自己已执行的 GTID 集合 2. 主服务器找出从服务器尚未执行的事务 3. 从服务器接收并执行这些事务
-
复制恢复与故障处理
sql-- 发生故障后,无需指定具体位置 CHANGE MASTER TO MASTER_HOST='new_master', MASTER_AUTO_POSITION=1;
选择建议
何时使用基于位置的复制
- MySQL 5.6 以前的版本
- 需要细粒度控制复制位置
- 复制链路涉及到非 InnoDB 表
- 重度依赖复制过滤功能
何时使用 GTID 复制
- MySQL 5.6 及以后版本
- 需要高可用自动故障切换
- 复杂的复制拓扑(如环形复制、多源复制)
- 希望简化复制管理和故障恢复
- 主要使用 InnoDB 存储引擎
技术注意事项
-
GTID 模式下的限制
- 不能在同一事务中同时创建临时表和非临时表
- CREATE TABLE ... SELECT 语句限制
- 不支持 SQLBIN 二进制日志格式
-
混合复制部署考虑
- 从 MySQL 8.0.17 开始支持更灵活的复制方式选择
- 可以同时保留两种复制技术的优点
-
升级与迁移注意事项
- 从基于位置转换到 GTID 复制需要特定的升级步骤
- 可能需要临时关闭复制进行切换
GTID 复制通常是现代 MySQL 部署的推荐选择,特别是在需要自动化高可用架构的环境中。不过,在某些特定场景下,基于位置的复制仍然有其应用价值。