Database

mysql的主从同步机制

Mysql的主从同步机制

InnoDBMySQL

Mysql的主从同步机制

mysql中的主从同步机制其实就是一种数据复制的技术,将主库也就是master中的数据同步到一个或多个从库也就是slave中。

主要是通过二进制文件也就是bin log实现的。主库在执行写操作时,会将对应的操作记录到bin log 中,然后推送给从库,从库重放对应的日志即可完成复制。

同步的核心流程大致如下:

  1. 客户端发起提交事务请求
  2. 主库接受请求,并将更新写入bin log中
  3. 主库有一个dump线程监听bin log文件的变更,主库写完bin log后,dump线程监听到有更新就会给从库推送更新事件
  4. 从库收到更新事件后开启一个I/O线程将bin log中的变更数据读取下来,写入从库的relay log中(relay log用于主从同步时,临时存放I/O线程拉取的更新数据,解耦I/O和执行,否则如果执行和拉取都是一个线程,那么就会有新更新时如果此时线程在写那么拉取就被阻塞,性能差。在写多的场景下,主从库的数据差异可能会放大)
  5. 从库的sql线程从relay log中重放日志,更新数据
  6. 更新完后给主库响应

MySQL 主从复制类型

mysql支持异步复制,同步复制以及半同步复制

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

异步复制

简单地来说就是主库不需要等待从库的响应,更新完bin log,推送了bin log更新事件后就直接给客户端响应了。让从库自行读取bin log,然后重放日志。

他的性能比较好,但是如果主库响应完后就挂了,那么此时从库不一定就有刚更新的数据,就导致了数据缺失。

同步复制

同步复制的性能很差,但是数据一致性很高,但绝大多数场景下并不要求很高的数据一致性。他则是需要同步等待所有从库的响应,才会响应客户端,导致客户端被阻塞,正常业务无法执行

半同步复制

他的性能折中,数据一致性也能比较好的保障,他只需要部分从库的响应即可响应客户端。比如我现在有五个从库,我设置参数为2,那么只要有任意两个从库响应说复制成功了,主库就直接响应客户端。这样只有主库和这两个库都挂了,才会导致数据缺失。

并行复制

在以前从库是通过一个 SQL 线程按照顺序逐条执行主库的 binlog 日志指令(即从 relay log 重放事件)。对于主库的高并发写入操作,这种串行执行的方式会导致从库的复制速度跟不上主库,从而产生主从延迟问题。

所以 MySQL 引入了并行复制,说白了就是通过 多个 SQL 线程 来并发执行重放事件。MySQL 提供了以下几种并行复制模式。

Mysql 5.6 基于库级别的并行复制

假设主库有多个数据库(如 db1db2),在从库上,db1 的事务和 db2 的事务可以同时执行。即将不同数据库上的事务分配到不同的 SQL 线程中执行。但实际情况是,在绝大多数的项目中主库都集中在一个数据库上,这个就没啥用了。

MySQL 5.7 基于逻辑时钟(LOGICAL_CLOCK)事务的并行复制

事实上主库提交事务并不是一个一个提交的,而是多个事务批量提交,即

事务 A \
事务 B  } —— 同一批 commit
事务 C /

这就叫 group commit(组提交)。在主库中同一批提交的事务在binlog中是一组

主要是磁盘的IO很慢很影响性能。每一个事务提交都会刷redo log和bin log

于是MySQL 会把 已经完成执行阶段、等待提交的事务 放进同一批。一起提交

而LOGICAL_CLOCK 并行复制正是利用了主库 group commit 产生的提交批次信息,将同一批次内的事务在从库并行执行。在 group commit 中是否能批量提交与表无关,而只取决于事务是否能同时进入提交阶段,这由锁和事务隔离机制保证安全性。

需要注意的是:能进入同一个 group commit 的事务,说明: 👉 它们在主库的执行阶段已经被证明“互不依赖”。

mysql会把那些同一时刻执行完成,并等待提交的事务放进同一批次提交。在逻辑上就避免了有“依赖的”事务:

比如: T1: UPDATE user SET score = 10 WHERE id = 1; T2: UPDATE user SET score = 20 WHERE id = 1;

他们的执行过程是: T1 拿锁 → 执行 T2 等锁 T1 commit T2 执行 → commit

👉 它们不可能同时进入 commit 阶段 👉 不可能进入同一个 group commit 👉 binlog 中一定是不同 batch

能够进入同一批事务,就意味着:

  1. 没有锁冲突
  2. 可以同时执行完
  3. 不同表/不同记录
  4. 一起进入commit阶段

这时候主库以及认定,两个事务无论谁先谁后执行都无所谓,所以从库在复制时,对于同一批次的事务可以并行执行,无需考虑执行顺序。而对于不同批次的事务,则需要按照顺序执行。

post.comments