MySQL主从复制原理

MySQL主从复制和Redis主从复制有点像, 可以相互对照一下. Redis主从复制

Binary Log日志格式

  • STATEMENT
    记录每一条会修改数据的SQL语句. 相比ROW来说日志量少, 性能更高, 但在某些特殊情况下会丢失数据, 比如使用sleep()函数等.
  • ROW
    如果是表结构变更, 仍然以STATEMENT格式记录SQL, 对于其他增删改SQL语句, 会将其分解为基于行更改的SQL语句. ROW格式相比STATEMENT格式来说日志量更大, 性能会低一些, 但数据不会丢失.
  • MIXED
    这是STATEMENT和ROW两种格式的结合, 它根据每一条具体的SQL语句来选择使用STATEMENT或ROW.

在这里插入图片描述

MySQL主从复制的原理

异步复制

MySQL主从复制默认是异步复制.

MySQL主从复制原理_第1张图片

  • 主库修改数据会记录Binary Log日志, 只有记录Binary Log日志成功后, 事务才能提交.
  • 从库接入后会开启一个IO线程, 根据position偏移量从主库的Binary Log日志中拷贝数据.
  • 将拷贝过来的数据写入Relay Log中.
  • 开启一个SQL线程从Relay Log日志中读取SQL, 然后再执行.

半同步复制

半同步复制是在异步复制的基础上进行优化, 即主库写入binlog日志之后, 会立即将数据同步到从库, 从库将binlog日志写入自己本地的Relay Log之后, 会返回一个ack命令给主库, 主库只有接收到至少一个从库的ack命令之后, 才会认为写操作完成.

半同步复制插件: semisync_master.so

并行复制

并行复制是对异步复制导致的主从同步延时问题的解决方案.

(1) 为什么会产生主从同步延时呢?

主库写入binlog日志是多线程并发执行的, 而从库执行Relay Log日志中的SQL是单线程执行的, 所以当主库的写并发太大时, 就会导致主从同步延时. 解决这个问题的方向就是让从库多线程并发地执行Relay Log日志中的SQL.

并行复制可以基本解决主从同步延迟的问题, 但当主库的写并发太大时, 还是会有延迟, 这时就只能拆分主库了, 降低单库的写并发.

(2) 并行复制的原理

MySQL5.6是基于库的并行复制, 即不同数据库的SQL可以并发地执行, 而MySQL5.7是基于组提交的并行复制, 即同一组的事务可以并发地执行, 我们来看下具体实现.

MySQL主从复制原理_第2张图片

  • SQL层有一个全局的logical clock: commit_clock
  • 当事务进入prepare阶段时(执行SQL, 但还未提交), 从commit_clock获取一个逻辑时间保存在binlog中.(last_committed)
  • 当事务准备commit之前, 从commit_clock再获取一个逻辑时间保存在binlog中.(sequence_number)
  • last_committed - sequence_number能覆盖地就属于同一组(能同时执行说明没有锁冲突)
  • 从节点对属于同一组事务的binlog会并发地执行.

如何解决MySQL主库宕机导致的数据丢失情况?

使用半同步复制来解决这个问题.

如何解决主从同步延时的问题?

(1) 主从同步延时的原因

主库写入binlog日志是多线程并发执行的, 而从库执行Relay Log日志中的SQL是单线程执行的, 所以当主库的写并发太大时, 就会导致主从同步延时.

(2) 解决办法

  • 并行复制
    MySQL5.7开启并行复制后, 主从同步延时问题基本就解决了.
  • 分库
    主从同步延时的根本原因还是主库写并发太高, 我们可以通过分库来降低单库的写并发.
  • 优化代码
    较短时间的主从同步延时是可以接受的, 我们不要写那种insert+select+update式的语句, 即插入一条数据后立即查询, 然后再修改.

你可能感兴趣的:(MySQL笔记,mysql,主从复制原理,数据库)