主备同步流程
主库备库建立一个长连接,主库内部有一个线程专门维护这个长连接。
事务的同步过程
- 备库通过change master命令,设置主库的ip,端口用户名密码,以及从那个位置开始请求binlog,位置包含文件名和日志偏移量。
- 备库执行start slave 命令,备库会启动两个线程,io_thread和sql_thread。io线程负责与主库建立连接
- 主库校验用户名密码后,开始按照备库传过来的位置,从本地读取binlog 发给备库
- 备库拿到binlog后,写到本地文件称为中转日志(relay log)
- sql_thread读取中转日志,解析日志的命令并执行。(sql线程后面演化为多线程)
同步流程
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格式也是可以的。