训练营6:什么是MySQL的主从复制机制?它是如何实现的?

一.核心结论

MySQL的主从复制机制是用于MySQL集群将主机Master上的数据同步到一个或多个从机slave中,主要是通过binlog实现数据复制。

二.分层理解

1.核心构成

MySQL集群是由一个主机多个从机组成,主机主要接收事务请求执行写操作,从机负责读取与备份数据,从而实现读写分离,而主从复制就是从机用于数据备份的一种机制。

主机:

Bin log:记录所有数据变更(DDL/DML)。 Binlog Dump线程:向从库发送Binlog事件。

从机:

  • I/O线程:连接主库,拉取Binlog并写入本地Relay Log。
  • SQL线程:读取Relay Log,重放SQL语句,更新数据。
  • Relay Log:从库暂存主库的Binlog,供SQL线程消费。

2.核心流程

  1. 建立连接:从机开启主从复制与主机建立连接,生成I/O线程和SQL线程
  2. 接收请求:主机接收到事务请求,将写操作写入binlog中
  3. I/O线程拉取日志:Binlog Dump线程监听到binlog发生变动会将事件推送给从机I/O线程
  4. 写入数据:从机通过I/O线程将数据写入relaylog中
  5. SQL线程重放日志:然后通过SQL线程解析relaylog,按顺序执行sql更新数据,保证数据一致性

3.主从复制类型

  • 同步复制:主库同步等待所有从库确认收到数据(性能差,数据一致性高)。
  • 异步复制(默认):主库不需要等待从库的响应(性能较高,数据一致性低)。
  • 半同步复制:主库等待至少一个从库确认收到数据(性能折中,数据一致性较高)。

4.拓展知识

(1)InnoDB修改操作执行流程

  • 数据读取
    • 当需要修改数据时,InnoDB首先在Buffer Pool(缓冲池)中查找目标数据页。
    • 若数据页未加载到Buffer Pool,则从磁盘读取到Buffer Pool中(避免直接操作磁盘,提升性能)。
  • 记录Undo Log(保证事务回滚与MVCC)
    • 在修改数据页之前,将原始数据写入Undo Log,用于事务回滚和实现多版本并发控制(MVCC)。
    • Undo Log的写入遵循先写日志后修改数据的原则,确保崩溃恢复时能回滚未提交事务。
  • 更新bufferpool数据:
    • 在内存中直接修改Buffer Pool中的数据,生成新版本数据、
    • 修改后的数据页会被标记为脏页,与磁盘数据形成差异
  • 写入Redo Log Buffer(Prepare阶段)
    • 将数据变更操作记录到Redo Log Buffer中,此时Redo Log状态为Prepare
  • 两阶段提交(2PC)
    • Prepare阶段:将Redo Log Buffer中的Prepare状态日志刷盘(持久化到磁盘),确保即使后续崩溃也能通过日志恢复。
    • 写入Binlog:生成Binlog(用于主从复制与数据恢复),并将Binlog写入磁盘。
    • Commit阶段:将Redo Log状态标记为Commit,并再次刷盘。至此,事务提交完成。
  • 异步刷脏页(数据持久化)
    • 脏页不会立即写入磁盘,而是由后台线程通过Checkpoint机制异步刷盘,减少事务提交的延迟。

口语化 1. 首先,从Buffer Pool中读取目标数据页,若未命中则从磁盘加载。 2. 修改前,将原始数据写入Undo Log,用于事务回滚和MVCC。 3. 在Buffer Pool中更新数据,标记为脏页。 4. 将修改操作记录到Redo Log Buffer,状态为Prepare,并刷盘(持久化)。 5. 写入Binlog并刷盘,确保主从复制和数据恢复的可靠性。 6. 提交事务,将Redo Log标记为Commit并再次刷盘。 7. 最后,脏页由后台线程异步刷回磁盘。整个过程通过两阶段提交和日志先行(WAL)机制,保证了事务的ACID特性。

(2)如何解决主从复制的延迟?

mysql主从复制的延迟是必然存在的,只能减少延迟的时间,常见的解决方式有以下几种:

  • 二次查询。如果从库查不到数据,则再去主库查一遍,由 API 封装这个逻辑即可,算是一个兜底策略,比较简单。不过等于读的压力又转移到主库身上了,如果有不法分子故意查询必定查不到的查询,这就对主库产生冲击了。
  • 强制将写之后立马读的操作转移到主库上。这种属于代码写死了,比如一些写入之后立马查询的操作,就绑定在一起,写死都走主库。不推荐,比较死板。
  • 关键业务读写都走主库,非关键还是读写分离。比如上面我举例的用户注册这种,可以读写主库,这样就不会有登陆报该用户不存在的问题,这种访问量频次应该也不会很多,所以看业务适当调整此类接口。
  • 使用缓存,主库写入后同步到缓存中,这样查询时可以先查询缓存,避免了延迟的问题,不过又引入了缓存数据一致性的问题。
  • 并行复制:利用 MySQL 并行复制功能提升效率、减少延迟
    • MySQL 5.6 库级别并行复制:基于 Schema(库)进行并行复制,每个库可拥有自己的复制线程来并行处理不同库的写入,提升性能。但多数业务为单库,该方案实用性欠佳,未获开发者和 DBA 认可。
    • MySQL 5.7 基于组提交的并行复制(MTS):组提交将多个事务的提交操作合并为批处理,减少磁盘 IO 和锁定开销。当多个事务进入 Prepare 阶段且锁无冲突(即修改不同行记录)时,可在从库用多个 SQL 线程并行执行组提交中的 SQL,提高主从复制效率,降低延迟。不过该方案依赖主库并行度,主库并发不高时可能无法进行组提交,也就无法使用并行复制优化。同时如果主库的SQL执行并没有那么频繁,那么时间间隔可能就会超过组提交的那两个参数阈值,就不会进行组提交。那么复制的时候就不能用并行复制了。
    • MySQL 8.0 基于 WRITESET 的并行复制:为解决 MySQL 5.7 方案的局限性而引入。即便主库串行提交事务,只要事务间不冲突,在从库就能并行回放。WRITESET 是使用 C++ STL 中 set 容器的集合,元素为行数据主键和唯一键的 hash 值(与指定算法有关)。通过检测事务更新记录的 hash 值是否冲突,判断能否并行回放,确保同一 write_set 中的变更不冲突,进而可通过多个线程并行回放 SQL 。

三.口语回答

MySQL主从复制是MySQL集群数据同步的一种机制,它是由一个主机master和多个从机slave组成,核心是主机的binlog日志、binlogdump线程和从机的relaylog日志和I/O、SQL两个线程。它的执行流程是先让从机与主机建立连接,生成IO和SQL线程;当主机接收到事务请求时会修改binlog日志,binlogDump线程监听到binlog日志发生变化会将事件推送到从机的IO线程,I/O线程接收到数据后写入relaylog日志,最后通过SQL线程解析relaylog数据,按照顺序执行sql更新数据,从而保持主机与从机的数据一致性。

0个评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
下载 APP