MySQL 主从复制全面指南

2 minute read

1. MySQL主从复制概述

MySQL主从复制是MySQL数据库提供的一种重要功能,它允许将一个数据库服务器(主库)的数据实时复制到一个或多个数据库服务器(从库)上。主从复制是构建高可用、高性能MySQL架构的基础技术。

1.1 主从复制的作用

  • 读写分离:主库负责写入操作,从库负责读取操作,分散数据库访问压力
  • 数据备份:从库作为主库的实时备份,提高数据安全性
  • 高可用性:当主库出现故障时,可以快速切换到从库,保证服务持续运行
  • 数据分析:可以在从库上进行数据分析、报表生成等操作,不影响主库性能

2. MySQL主从复制原理

2.1 基本原理

MySQL主从复制基于二进制日志(binlog)实现,整个复制过程涉及三个线程:

  1. Binlog dump线程(主库):当从库连接到主库时,主库会创建一个binlog dump线程,用于读取主库上的二进制日志,并发送给从库

  2. I/O线程(从库):负责连接主库,接收主库发送的二进制日志,并将其写入本地的中继日志(relay log)

  3. SQL线程(从库):负责读取中继日志中的事件,并在从库上重放这些事件,使从库的数据与主库保持一致

2.2 复制过程

  1. 写入binlog:主库在执行事务时,会将所有的数据变更记录到二进制日志(binlog)中

  2. 同步binlog:从库的I/O线程连接到主库,请求获取二进制日志,主库的binlog dump线程读取二进制日志并发送给从库

  3. 写入relay log:从库的I/O线程将接收到的二进制日志写入本地的中继日志(relay log)

  4. 回放relay log:从库的SQL线程读取中继日志中的事件,并在从库上执行这些事件,使从库的数据与主库保持一致

3. MySQL主从复制模式

3.1 按拓扑结构分类

3.1.1 一主一从

最简单的主从复制结构,一个主库对应一个从库。适用于小型应用或作为更复杂架构的基础。

3.1.2 一主多从

一个主库对应多个从库。主库负责所有的写操作,多个从库分担读操作,提高系统的读性能和可用性。

3.1.3 双主复制(主主复制)

两个服务器互为主从,每个服务器既是主库也是从库。这种结构提供了更高的可用性,但需要解决数据冲突问题。

3.1.4 级联复制

从库可以作为其他从库的主库,形成一个复制链。这种结构可以减轻主库的复制压力,但会增加数据延迟。

3.2 按同步方式分类

3.2.1 异步复制(Asynchronous Replication)

  • 原理:主库执行完事务后立即返回给客户端,不等待从库的响应
  • 优点:性能高,主库写入速度不受从库影响
  • 缺点:无法保证数据一致性,主库宕机可能导致数据丢失
  • 适用场景:对数据一致性要求不高,但对性能要求较高的应用

3.2.2 半同步复制(Semi-synchronous Replication)

  • 原理:主库执行完事务后,至少等待一个从库接收并写入relay log后才返回给客户端
  • 优点:提高了数据安全性,降低了数据丢失的风险
  • 缺点:相比异步复制,性能略有下降
  • 适用场景:对数据一致性和性能都有一定要求的应用

3.2.3 全同步复制(Synchronous Replication)

  • 原理:主库执行完事务后,必须等待所有从库执行完成才返回给客户端
  • 优点:保证了数据的强一致性
  • 缺点:性能较低,从库故障会影响主库可用性
  • 适用场景:对数据一致性要求极高的金融、支付等关键业务

3.3 按复制格式分类

3.3.1 基于语句的复制(Statement-based Replication,SBR)

  • 原理:记录修改数据的SQL语句,在从库上重新执行
  • 优点:日志量小,节省带宽
  • 缺点:某些函数和触发器可能导致主从不一致

3.3.2 基于行的复制(Row-based Replication,RBR)

  • 原理:记录行数据的变化,在从库上重放这些变化
  • 优点:保证数据一致性,支持所有SQL语句
  • 缺点:日志量大,占用带宽

3.3.3 混合复制(Mixed Replication)

  • 原理:默认使用基于语句的复制,在某些情况下自动切换到基于行的复制
  • 优点:结合了SBR和RBR的优点
  • 缺点:复杂度增加

4. GTID复制模式

4.1 GTID概述

GTID(Global Transaction ID) 是 MySQL 5.6 及以上版本引入的一种全局事务标识机制,用于在数据库集群中唯一标识每个事务,GTID由两部分组成:源服务器ID(UUID)和事务ID,格式为 server_uuid:transaction_id

GTID 的主要作用包括:

  1. 事务追踪与一致性保障:通过为每个事务分配唯一标识,GTID 确保事务在主从复制中不会被重复执行或丢失,从而提高数据一致性。
  2. 简化复制管理:GTID 允许从库自动定位复制起点(通过 MASTER_AUTO_POSITION=1),无需手动指定 binlog 文件和位置,降低了配置复杂度。
  3. 支持故障恢复与主从切换:在故障恢复或主从切换场景中,GTID 能够快速确定事务执行状态,帮助实现无缝切换和数据同步。
  4. 支持多主复制与组复制:GTID 是 MySQL Group Replication 等全同步复制模式的基础,确保分布式环境中事务的正确管理和冲突检测。

4.2 GTID复制的优势

  • 简化故障转移:从库可以自动找到正确的复制位置,无需手动指定binlog文件和位置
  • 简化主从搭建:不需要确定binlog位置,直接使用GTID即可
  • 提高数据一致性:可以确保每个事务只被应用一次
  • 方便复制监控:可以清晰地知道哪些事务已经被复制

4.3 GTID复制的工作原理

  1. 主库为每个事务生成一个全局唯一的GTID
  2. 主库将事务和GTID一起写入binlog
  3. 从库接收到binlog后,提取GTID和事务内容
  4. 从库检查GTID是否已经执行过,如果已执行则跳过,否则执行该事务
  5. 从库记录已执行的GTID集合

5. MySQL主从复制配置

5.1 前提条件

  • 两台或多台MySQL服务器
  • 主库和从库的MySQL版本兼容
  • 网络连通性良好
  • 主库开启二进制日志

5.2 主库配置

  1. 修改主库的配置文件(my.cnf):
[mysqld]
# 服务器唯一ID
server-id = 1

# 开启二进制日志
log-bin = mysql-bin

# 二进制日志格式(推荐ROW格式)
binlog_format = ROW

# 指定需要复制的数据库(可选)
# 生产环境建议禁用,主库记录所有变更
# binlog-do-db = db_name

# 指定不需要复制的数据库(可选)
# binlog-ignore-db = db_name
  1. 重启MySQL服务:
sudo systemctl restart mysql
  1. 创建用于复制的用户:
CREATE USER 'repl'@'%' IDENTIFIED BY 'password';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
FLUSH PRIVILEGES;
  1. 获取主库状态信息:
SHOW MASTER STATUS;

记录下File和Position的值,后续在从库配置中需要使用。

5.3 从库配置

  1. 修改从库的配置文件(my.cnf):
[mysqld]
# 服务器唯一ID(必须与主库不同)
server-id = 2

# 开启中继日志(可选)
relay-log = relay-bin

# 指定需要复制的数据库(可选)
# replicate-do-db = db_name

# 指定不需要复制的数据库(可选)
# replicate-ignore-db = db_name
  1. 重启MySQL服务:
sudo systemctl restart mysql
  1. 配置从库连接到主库:
CHANGE MASTER TO
  MASTER_HOST='主库IP',
  MASTER_PORT=3306,
  MASTER_USER='repl',
  MASTER_PASSWORD='password',
  MASTER_LOG_FILE='mysql-bin.000001',  -- 使用主库状态中的File值
  MASTER_LOG_POS=123;                 -- 使用主库状态中的Position值
  1. 启动从库复制进程:
START SLAVE;
  1. 检查从库状态:
SHOW SLAVE STATUS\G

确保Slave_IO_Running和Slave_SQL_Running都是Yes。

5.4 GTID复制配置

  1. 主库配置(my.cnf):
[mysqld]
server-id = 1
log-bin = mysql-bin
binlog_format = ROW

# 启用GTID
gtid_mode = ON
enforce_gtid_consistency = ON
log_slave_updates = ON
  1. 从库配置(my.cnf):
[mysqld]
server-id = 2

# 启用GTID
gtid_mode = ON
enforce_gtid_consistency = ON
log_slave_updates = ON
  1. 在从库上配置复制:
CHANGE MASTER TO
  MASTER_HOST='主库IP',
  MASTER_PORT=3306,
  MASTER_USER='repl',
  MASTER_PASSWORD='password',
  MASTER_AUTO_POSITION = 1;  -- 使用GTID自动定位

6. 多线程复制配置

MySQL 5.7引入了增强型多线程复制(Enhanced Multi-threaded Slave),可以大幅提高从库的复制性能,减少主从延迟。

6.1 多线程复制类型

MySQL 5.7支持两种多线程复制类型:

  1. DATABASE:基于库的并行复制,每个数据库对应一个复制线程(MySQL 5.6引入)
  2. LOGICAL_CLOCK:基于组提交的并行复制,同一个数据库下可以有多个线程并行执行(MySQL 5.7引入,推荐使用)

6.2 多线程复制配置

在从库上配置多线程复制:

-- 停止从库复制
STOP SLAVE;

-- 设置复制类型为LOGICAL_CLOCK(基于组提交的并行复制)
SET GLOBAL slave_parallel_type = 'LOGICAL_CLOCK';

-- 设置并行工作线程数(建议设置为CPU核心数)
SET GLOBAL slave_parallel_workers = 8;

-- 启动从库复制
START SLAVE;

6.3 多线程复制的持久化配置

在从库的my.cnf文件中添加以下配置:

[mysqld]
# 设置复制类型为LOGICAL_CLOCK
slave_parallel_type = LOGICAL_CLOCK

# 设置并行工作线程数(建议设置为CPU核心数)
slave_parallel_workers = 8

# 将master.info和relay.info保存在表中
master_info_repository = TABLE
relay_log_info_repository = TABLE

# 从库宕机后自动放弃损坏的relay-log,并重新从master上获取二进制日志
# 这样能保证relay-log的完整性,该功能默认是关闭的,建议开启
relay_log_recovery = ON

# 保证事务提交顺序
slave_preserve_commit_order = ON

7. 主从复制监控与延迟处理

7.1 主从延迟的原因

  1. 网络延迟:主从服务器之间的网络延迟
  2. 从库性能问题:从库的硬件配置比主库差
  3. 从库负载过高:从库上有大量查询操作
  4. 大事务执行:主库上执行了大事务,从库需要更多时间处理
  5. 单线程复制限制:MySQL 5.6之前的单线程复制模式效率低下
  6. 无主键或索引不合理:从库上的表缺少主键或索引不合理,导致回放效率低

7.2 监控主从延迟

  1. 使用Seconds_Behind_Master参数
SHOW SLAVE STATUS\G

查看输出中的Seconds_Behind_Master值,该值表示从库与主库的延迟秒数:

  • 0:表示无延迟
  • NULL:表示从库的IO线程或SQL线程出现问题
  • 大于0:表示存在延迟,值越大延迟越严重
  1. 比较二进制日志位置

比较主库的当前二进制日志文件和位置与从库的Master_Log_File和Read_Master_Log_Pos,判断是否存在差异。

  1. 使用pt-heartbeat工具

Percona Toolkit中的pt-heartbeat工具可以更准确地监控主从延迟。

7.3 减少主从延迟的方法

  1. 优化网络环境:确保主从服务器之间的网络连接稳定、延迟低

  2. 提升从库硬件配置:为从库配置更好的硬件,特别是CPU、内存和磁盘I/O

  3. 使用多线程复制:在MySQL 5.7及以上版本中启用多线程复制

  4. 优化SQL和索引:确保表有主键,优化索引结构,避免慢查询

  5. 避免大事务:将大事务拆分为小事务,或在业务低峰期执行

  6. 调整从库参数
    • 关闭从库的二进制日志(如果不需要)
    • 调整innodb_flush_log_at_trx_commit和sync_binlog参数
  7. 使用SSD存储:使用SSD可以显著提高I/O性能

8. 主从复制的数据一致性保障

8.1 数据一致性问题

主从复制中的数据一致性问题主要来自两个方面:

  1. 主库日志写入不成功:导致从库无法获取完整的变更日志
  2. 从库回放失败:从库在应用主库日志时出现错误

8.2 提高主库数据安全性

配置主库参数以确保数据和日志的安全:

[mysqld]
# 开启InnoDB双写缓冲区,防止部分页写入
innodb_doublewrite = ON

# 支持两阶段提交
innodb_support_xa = ON

# 每次事务提交都刷新日志到磁盘
innodb_flush_log_at_trx_commit = 1

# 每次事务提交都刷新binlog到磁盘
sync_binlog = 1

这些参数开启后可以显著提升数据一致性和持久性,但是以性能为代价,适合对数据完整性要求极高的生产环境。如果在高并发场景下遇到性能问题,可以根据业务需求适当调整,并在调整前做好测试和监控。

8.3 复制模式选择

根据业务对数据一致性的要求,选择合适的复制模式:

  1. 异步复制:适用于对性能要求高,对数据一致性要求不严格的场景
  2. 半同步复制:适用于对数据一致性和性能都有要求的场景
    • 配置参数:rpl_semi_sync_master_enabled = 1rpl_semi_sync_slave_enabled = 1
    • 设置等待点:rpl_semi_sync_master_wait_point = AFTER_SYNC(MySQL 5.7)
  3. 组复制(Group Replication):适用于对数据一致性要求极高的场景
    • MySQL 5.7.17及以上版本支持
    • 基于XCom协议(Paxos变种)实现的分布式一致性技术
    • 支持单主和多主两种复制模式
    • 提供自动故障检测、成员管理和脑裂保护等企业级特性

9. 主从复制的故障处理

9.1 常见故障类型

  1. 从库IO线程故障:无法从主库获取二进制日志
  2. 从库SQL线程故障:无法正确应用中继日志
  3. 主库故障:主库服务不可用
  4. 数据不一致:主从数据出现差异

9.2 故障排查与修复

  1. IO线程故障
    • 检查网络连接
    • 验证复制用户权限
    • 查看主库二进制日志是否存在
  2. SQL线程故障
    • 查看错误日志
    • 跳过错误事务:SET GLOBAL sql_slave_skip_counter = 1; START SLAVE;
    • 修复数据不一致
  3. 主库故障
    • 将从库提升为主库
    • 重新配置其他从库连接到新主库

9.3 主从切换

  1. 计划内切换
    • 停止主库写入
    • 等待从库完全同步
    • 将从库提升为主库
    • 重新配置应用连接
  2. 故障切换
    • 确认主库不可用
    • 选择延迟最小的从库作为新主库
    • 提升从库为主库
    • 重新配置应用连接
    • 恢复原主库作为从库

10. 主从复制最佳实践

10.1 架构设计

  1. 合理规划服务器数量:根据业务需求和预算确定主从服务器数量
  2. 考虑地理分布:跨地域部署可提高灾备能力,但会增加网络延迟
  3. 使用负载均衡:在多个从库之间分配读请求

10.2 配置优化

  1. 使用GTID复制:简化故障恢复和主从搭建
  2. 启用多线程复制:提高从库复制性能
  3. 合理设置二进制日志格式:推荐使用ROW格式
  4. 定期清理二进制日志:避免磁盘空间耗尽

10.3 监控与维护

  1. 建立完善的监控系统:监控主从状态、复制延迟、服务器资源等
  2. 定期备份:即使有从库作为备份,也应定期进行全量备份
  3. 定期检查数据一致性:使用工具验证主从数据一致性
  4. 演练故障恢复:定期进行主从切换演练

10.4 安全性考虑

  1. 使用SSL加密复制连接:保护数据传输安全
  2. 限制复制用户权限:只授予必要的权限
  3. 设置防火墙规则:限制对MySQL端口的访问

总结

MySQL主从复制是构建高可用、高性能数据库架构的重要技术。通过合理配置和优化,可以实现读写分离、数据备份和故障转移等功能。随着MySQL版本的发展,GTID复制和多线程复制等新特性使主从复制更加强大和易用。在实际应用中,应根据业务需求选择合适的复制模式和配置,并建立完善的监控和维护机制,确保主从复制的稳定运行。

Tags:

Categories:

Updated: