第二十四讲

100 阅读6分钟

主备同步流程

主库备库建立一个长连接,主库内部有一个线程专门维护这个长连接。

事务的同步过程

  • 备库通过change master命令,设置主库的ip,端口用户名密码,以及从那个位置开始请求binlog,位置包含文件名和日志偏移量。
  • 备库执行start slave 命令,备库会启动两个线程,io_thread和sql_thread。io线程负责与主库建立连接
  • 主库校验用户名密码后,开始按照备库传过来的位置,从本地读取binlog 发给备库
  • 备库拿到binlog后,写到本地文件称为中转日志(relay log)
  • sql_thread读取中转日志,解析日志的命令并执行。(sql线程后面演化为多线程)

同步流程

image

binlog的三种格式

statement

statement 记录逻辑是按照commit提交的顺序 有些statement格式的binlog可能会导致主备不一致,所以要使用row格式。(带limit的更改语句,很可能会出现主备数据不一致的情况)

row

row 记录方式是每行数据的变动情况 row格式的缺点是,很占空间。比如你用一个delete语句删掉10万行数据,用statement的话就是一个SQL语句被记录到binlog中,占用几十个字节的空间。但如果用row格式的binlog,就要把这10万条记录都写到binlog中。

mixed

mixed格式的意思是,MySQL自己会判断这条SQL语句是否可能引起主备不一致,如果有可能,就用row格式,否则就用statement格式。

mixed格式可以利用statment格式的优点,同时又避免了数据不一致的风险。

当binlog_format使用row格式的时候,binlog里面记录了真实删除行的主键id,这样binlog传到备库去的时候,就肯定会删除id=4的行,不会有主备删除不同行的问题。

《25讲》

主备延迟

所谓主备延迟,就是同一个事务,在备库执行完成的时间和主库执行完成的时间之间的差值。执行show slave status命令,它的返回结果里面会显示seconds_behind_master,用于表示当前备库延迟了多少秒。

主备延迟的来源

  • 备库所在机器的性能要比主库所在的机器性能差。
  • 备库的压力大
  • 大事务(例如:一次性地用delete语句删除太多数据)
  • 大表DDL
  • 备库的并行复制能力 (优秀评论补充: 6.表上无主键的情况(主库利用索引更改数据,备库回放只能用全表扫描,这种情况可以调整slave_rows_search_algorithms参数适当优化下) 7.设置的是延迟备库 8.备库空间不足的情况下)

可靠性优化策略的做法

  • 判断备库的seconds_behind_master,如果小于某个值(5s)才继续下一步,否则重试
  • 主库修改只读状态(readonly=true)
  • 判断备库seconds_behind_master的值,直到为0;
  • 修改备库可读写状态(readonly=false)
  • 把业务请求切到备库。

可靠性注重的是数据的同步,中间会有一个同步的时间周期内系统不可写。

可用性优先策略

不等主备数据同步,直接把连接切到备库B,并且让备库B可以读写,那么系统几乎就没有不可用时间了。

  • 可用性优先策略,binlog_format=mixed 主库A和备库B上出现了两行不一致的数据。
  • 可用性优先策略,binlog_format=row,最后只会有一行数据不一致。

(26讲)

备库同步延迟

5.6版本之前,MySQL只支持单线程复制,由此在主库并发高、TPS高时就会出现严重的主备延迟问题。5.6之后支持多线程复制,线程个数由参数slave_parallel_workers决定。(推荐 32核 8-16最好)

coordinator在分发中继日志的时候,需要满足以下这两个基本要求:

  • 不能造成更新覆盖。这就要求更新同一行的两个事务,必须被分发到同一个worker中。

  • 同一个事务不能被拆开,必须放到同一个worker中。

mariaDB并行复制策略

redo log组提交(group commit)优化, 而MariaDB的并行复制策略利用的就是这个特性:

  • 能够在同一组里提交的事务,一定不会修改同一行;

  • 主库上可以并行执行的事务,备库上也一定是可以并行执行的。

实现
  • 在一组里面一起提交的事务,有一个相同的commit_id,下一组就是commit_id+1;
  • commit_id直接写到binlog里面;
  • 传到备库应用的时候,相同commit_id的事务分发到多个worker执行;
  • 这一组全部执行完成后,coordinator再去取下一批执行

MySQL5.7的并行复制策略

MySQL5.7也提供了类似mariaDb的功能,由参数slave-parallel-type来控制并行复制策略:

  • 配置为DATABASE,表示使用MySQL 5.6版本的按库并行策略;

  • 配置为 LOGICAL_CLOCK,表示的就是类似MariaDB的策略。不过,MySQL 5.7这个策略,针对并行度做了优化。

5.7并行复制策略的核心思想:

  • 同时处于prepare状态的事务,在备库执行时是可以并行的;

  • 处于prepare状态的事务,与处于commit状态的事务之间,在备库执行时也是可以并行的。

5.7.22增加WRITESET策略

新增参数binlog-transaction-dependency-tracking,用来控制是否启用这个新策略。参数的可选值:

  • COMMIT_ORDER,根据同时进入prepare和commit来判断是否可以并行的策略

  • WRITESET 表示对于事物涉及更新的每一行,计算一个hash值,组成集合writeset。如果两个十五没有操作相同的行,也就表示writeset没有交集可以并行复制。

  • WRITE_SESSION,在writeset的基础上增加一个约束,即在主库上同一个线程先后执行的两个十五,在备库执行也要保证相同的先后顺序。

优势
  • writeset是在主库生成后直接写入到binlog里面的,这样在备库执行的时候,不需要解析binlog内容(event里的行数据),节省了很多计算量;
  • 不需要把整个事务的binlog都扫一遍才能决定分发到哪个worker,更省内存;
  • 由于备库的分发策略不依赖于binlog内容,所以binlog是statement格式也是可以的。