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

MySQL5.6的并行复制是库(schema)级别的,从库为每个库(schema)分配一个线程以此来提高复制效率

在MySQL 5.6版本之前,Slave服务器上有两个线程I/O线程和SQL线程。I/O线程负责接收二进制日志(更准确的说是二进制日志的event),SQL线程进行回放二进制日志。

MySQL5.6开启并行复制时,从库SQL线程就变为了coordinator线程,coordinator线程主要负责以下两部分的内容:

  • 判断可以并行执行,那么选择worker线程执行事务的二进制日志
  • 判断不可以并行执行,如该操作是DDL,亦或者是事务跨schema操作,则等待所有的worker线程执行完成之后,再执行当前的日志。

这意味着coordinator线程并不是仅将日志发送给worker线程,自己也可以回放日志,但是所有可以并行的操作交付由worker线程完成。coordinator线程与worker是典型的生产者与消费者模型。

对于有多个数据库的实例,开启并行的执行SQL,对从库能有较大的提升。但对单个库,开启多线程复制,性能可能比单线程还差。

MySQL 5.7 基于组提交(LOGICAL_CLOCK)的并行复制

MySQL5.7的并行复制是基于组提交(LOGICAL_CLOCK),主要思想是一个组提交的事务都是可以并行回放到从,原理是基于锁的冲突检测,因为这些事务都已进入到事务的prepare阶段,则说明事务之间没有任何冲突(否则就不可能提交)。

MySQL5.7并行复制引入了两个值last_committed和sequence_number。last_committed表示事务提交的时候,上次事务提交的编号,在主库上同时提交的事务设置成相同的last_committed。如果事务具有相同的last_committed,表示这些事务都在一组内,可以进行并行的回放。

总的来说就是:并发线程执行不同的事务只要在同一时刻能够commit(说明线程之间没有锁冲突),那么master节点就可以将这一组的事务标记并在slave机器上安全的进行并发重放主库提交的事务。所以尽可能的使所有线程能在同一时刻提交可以,可以极大的提高slave机器并发执行事务的数量使主备数据同步。

为了兼容MySQL 5.6基于库的并行复制,5.7引入了新的变量slave-parallel-type,其可以配置的值有:

  • DATABASE:默认值,基于库的并行复制方式

  • LOGICAL_CLOCK:基于组提交的并行复制方式

主端相关参数:

  • binlog_group_commit_sync_delay:表示binlog提交后等待延迟多少时间再同步到磁盘,单位是微秒,默认0,不延迟。设置延迟可以让多个事务在用一时刻提交,提高binlog组提交的并发数和效率,从而提高slave的吞吐量。

  • binlog_group_commit_sync_no_delay_count:表示在等待上面参数超时之前,如果有足够多的事务,则停止等待直接提交。单位是事务数,默认0。

从端相关参数:

  • slave_parallel_workers:设置为0,则MySQL 5.7退化为原单线程复制;设置为1,则SQL线程功能转化为coordinator线程,但是只有1个worker线程进行回放,也是单线程复制,性能反而比0还要差

那么如何知道事务是否在一组中?在MySQL 5.7是将组提交的信息存放在GTID中。那么如果用户没有开启GTID功能,即将参数gtid_mode设置为OFF呢?故MySQL 5.7又引入了称之为Anonymous_Gtid的二进制日志event类型,如:

mysqlbinlog --base64-output=decode-rows -vv mysql-bin.000005 | grep last_committed

#181228 11:26:19 server id 1  end_log_pos 219 CRC32 0x5f456ce6         Anonymous_GTID  last_committed=0        sequence_number=1       rbr_only=yes
#181228 11:26:25 server id 1 end_log_pos 489 CRC32 0x70efcdd6 Anonymous_GTID last_committed=1 sequence_number=2 rbr_only=yes
#181228 11:29:25 server id 1 end_log_pos 758 CRC32 0x988d75b0 Anonymous_GTID last_committed=1 sequence_number=3 rbr_only=yes
#181228 11:29:30 server id 1 end_log_pos 1027 CRC32 0x0441d881 Anonymous_GTID last_committed=1 sequence_number=4 rbr_only=yes
#181228 11:30:23 server id 1 end_log_pos 1299 CRC32 0xacef32af Anonymous_GTID last_committed=2 sequence_number=5 rbr_only=yes
#181228 11:41:24 server id 1 end_log_pos 1578 CRC32 0xe19286ec Anonymous_GTID last_committed=3 sequence_number=6 rbr_only=yes
#181228 11:43:14 server id 1 end_log_pos 1857 CRC32 0x29a01493 Anonymous_GTID last_committed=4 sequence_number=7 rbr_only=yes
#181228 11:43:30 server id 1 end_log_pos 2139 CRC32 0x9acc9bff Anonymous_GTID last_committed=1 sequence_number=8 rbr_only=yes
#181228 11:43:31 server id 1 end_log_pos 2436 CRC32 0x1c43ff17 Anonymous_GTID last_committed=1 sequence_number=9 rbr_only=yes
#181228 11:43:31 server id 1 end_log_pos 2778 CRC32 0x93632d39 Anonymous_GTID last_committed=1 sequence_number=10 rbr_only=yes
#181228 11:43:31 server id 1 end_log_pos 3210 CRC32 0xf2d0d2b3 Anonymous_GTID last_committed=1 sequence_number=11 rbr_only=yes
#181228 11:43:32 server id 1 end_log_pos 3822 CRC32 0xc1481a21 Anonymous_GTID last_committed=1 sequence_number=12 rbr_only=yes
#181228 11:43:32 server id 1 end_log_pos 4794 CRC32 0x58c1beae Anonymous_GTID last_committed=1 sequence_number=13 rbr_only=yes
#181228 11:43:33 server id 1 end_log_pos 6486 CRC32 0x4364eaf9 Anonymous_GTID last_committed=1 sequence_number=14 rbr_only=yes
#181228 11:43:33 server id 1 end_log_pos 9618 CRC32 0x2c5edb8c Anonymous_GTID last_committed=1 sequence_number=15 rbr_only=yes
#181228 11:43:34 server id 1 end_log_pos 15630 CRC32 0xa75cc5f4 Anonymous_GTID last_committed=1 sequence_number=16 rbr_only=yes
#181228 11:43:34 server id 1 end_log_pos 27437 CRC32 0xff0942d4 Anonymous_GTID last_committed=1 sequence_number=17 rbr_only=yes
#181228 11:43:34 server id 1 end_log_pos 50799 CRC32 0x1cb6f41f Anonymous_GTID last_committed=1 sequence_number=18 rbr_only=yes
#181228 11:43:35 server id 1 end_log_pos 97306 CRC32 0x5d03c9b8 Anonymous_GTID last_committed=1 sequence_number=19 rbr_only=yes
#181228 11:43:40 server id 1 end_log_pos 190103 CRC32 0x90e95ad1 Anonymous_GTID last_committed=19 sequence_number=20 rbr_only=yes
#181228 11:43:41 server id 1 end_log_pos 375445 CRC32 0x2515833b Anonymous_GTID last_committed=20 sequence_number=21 rbr_only=yes
#181228 11:43:41 server id 1 end_log_pos 745912 CRC32 0x81a72e5c Anonymous_GTID last_committed=21 sequence_number=22 rbr_only=yes

这意味着在MySQL 5.7版本中即使不开启GTID,每个事务开始前也是会存在一个Anonymous_Gtid,而这GTID中就存在着组提交的信息。

上面展示的日志内容可以看出,sequence_number 1~19 事物的last_committed都是1,意味着sequence_number 1~19 事物属于同一组可以并行提交。

配置基于组提交(LOGICAL_CLOCK)的并行复制

开启并行复制,只需在slave端加如下配置:


[mysqld]
#slave
slave_parallel_workers = 4 ###并行复制的线程数
slave_parallel_type = LOGICAL_CLOCK ###并行复制的类型,默认database
master_info_repository = table
relay_log_info_repository = table
relay_log_recovery = 1

slave_preserve_commit_order

slave端仅仅设置为LOGICAL_CLOCK也会存在问题,因为此时在slave上应用事务的顺序是无序的,和relay log中记录的事务顺序不一样,这样数据一致性是无法保证的,为了保证事务是按照relay log中记录的顺序来回放,就需要开启参数slave_preserve_commit_order。

开启slave_preserve_commit_order参数后,slave_parallel_type只能是LOGICAL_CLOCK

slave_preserve_commit_order=1

开启该参数后,worker线程将一直等待, 直到提交之前所有的事务。当从线程正在等待其他工作人员提交其事务时, 它报告其状态为等待前面的事务提交。所以虽然slave可以并行应用relay log,但commit部分仍然是顺序提交,其中可能会有等待的情况。

当开启slave_preserve_commit_order参数后,slave_parallel_type只能是LOGICAL_CLOCK,如果你有使用级联复制,那LOGICAL_CLOCK可能会使离master越远的slave并行性越差。

PS: 经测试这个参数只有在MySQL 5.7.19设置才有效

基于写集合的并行复制

writeset的思想是:不同事物修改了不同行的数据,那么可以视为同一组。MySQL 会对这个提交的事务中的一行记录做一个 HASH值,这些 HASH 值称为 writeset。writeset会存入一张 HASH 表。其他事务提交时会检查这张 HASH 表中是否有相同的记录,如果不相同,则视为同组,如果有相同,则视为不同组。怎么判断是否同组,依然采用了last_committed。

实现基于写集的并行复制,需要在master端添加如下配置:

[mysqld]
transaction_write_set_extraction=XXHASH64
binlog_transaction_dependency_tracking=WRITESET

这时候,我们分别执行两次insert操作,并解析出binlog:

BEGIN
/*!*/;
# at 291
#181228 17:04:29 server id 1 end_log_pos 340 CRC32 0xa581c6c2 Table_map: `mydb`.`ttt` mapped to number 108
# at 340
#181228 17:04:29 server id 1 end_log_pos 390 CRC32 0x72728e77 Write_rows: table id 108 flags: STMT_END_F
### INSERT INTO `mydb`.`ttt`
### SET
### @1=4652970 /* INT meta=0 nullable=0 is_null=0 */
### @2='ooooopppp' /* VARSTRING(60) meta=60 nullable=1 is_null=0 */
# at 390
#181228 17:04:29 server id 1 end_log_pos 421 CRC32 0xa7e2fcb6 Xid = 819
COMMIT/*!*/;
# at 421
#181228 17:04:36 server id 1 end_log_pos 486 CRC32 0xc7670134 Anonymous_GTID last_committed=1 sequence_number=2 rbr_only=yes
/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 486
#181228 17:04:36 server id 1 end_log_pos 558 CRC32 0xcf925205 Query thread_id=348 exec_time=0 error_code=0
SET TIMESTAMP=1545987876/*!*/;
BEGIN
/*!*/;
# at 558
#181228 17:04:36 server id 1 end_log_pos 607 CRC32 0x69875f63 Table_map: `mydb`.`ttt` mapped to number 108
# at 607
#181228 17:04:36 server id 1 end_log_pos 660 CRC32 0x03f67767 Write_rows: table id 108 flags: STMT_END_F
### INSERT INTO `mydb`.`ttt`
### SET
### @1=4652971 /* INT meta=0 nullable=0 is_null=0 */
### @2='xxxyyyyyyyyy' /* VARSTRING(60) meta=60 nullable=1 is_null=0 */
# at 660
#181228 17:04:36 server id 1 end_log_pos 691 CRC32 0xc00ede8f Xid = 820
COMMIT/*!*/;
# at 691
#181228 17:05:18 server id 1 end_log_pos 756 CRC32 0x154b4941 Anonymous_GTID last_committed=1 sequence_number=3 rbr_only=yes
/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;

可以看到两次执行的事物sequence_number 2 3 对应的 last_committed都是1

那么 writeset 最多可以并行执行多少个事务呢?近于 binlog_transaction_dependency_history_size 的一半

测试

待续

参考

https://www.cnblogs.com/zhoujinyi/p/5704567.html

http://blog.itpub.net/28218939/viewspace-1975809/

http://blog.itpub.net/28218939/viewspace-1975822/

http://blog.itpub.net/28218939/viewspace-1975856/

MySQL5.7 并行复制的学习的更多相关文章

  1. MySQL5.7 并行复制

    MySQL5.7 并行复制 1.缘由: 某天看到主从复制延时的告警有点频繁,就想着是不是彻底可以解决一下. 一般主从复制,有三个线程参与,都是单线程:Binlog Dump(主) ----->I ...

  2. MySQL5.7 并行复制配置

    转自:https://www.cnblogs.com/langdashu/p/6125621.html [MySQL] 号称永久解决了复制延迟问题的并行复制,MySQL5.7 一.缘由: 某天看到主从 ...

  3. MySQL的并行复制多线程复制MTS(Multi-Threaded Slaves)

    MySQL的并行复制多线程复制MTS(Multi-Threaded Slaves) http://www.tuicool.com/articles/m2Unmeq 姜承饶 简称MTS:基于binlog ...

  4. Mysql5.7实现主从复制、基于GTID的主从复制、并行复制

    (一.主从复制) 一.mysql主从复制原理    mysql的默认复制方式是主从复制.Mysql内建的复制功能是构建大型,高性能应用程序的基础.将Mysql的数据分布到多个系统上去,这种分布的机制, ...

  5. Centos7.5部署MySQL5.7基于GTID主从复制+并行复制+半同步复制+读写分离(ProxySQL) 环境- 运维笔记 (完整版)

    之前已经详细介绍了Mysql基于GTID主从复制的概念,原理和配置,下面整体记录下MySQL5.7基于GTID主从复制+并行复制+增强半同步复制+读写分离环境的实现过程,以便加深对mysql新特性GT ...

  6. MySQL5.7的组提交与并行复制

    从MySQL5.5版本以后,开始引入并行复制的机制,是MySQL的一个非常重要的特性. MySQL5.6开始支持以schema为维度的并行复制,即如果binlog row event操作的是不同的sc ...

  7. MySQL5.7的并行复制

    MySQL5.6开始支持以schema为维度的并行复制,即如果binlog row event操作的是不同的schema的对象,在确定没有DDL和foreign key依赖的情况下,就可以实现并行复制 ...

  8. [MySQL] 号称永久解决了复制延迟问题的并行复制,MySQL5.7

    一.缘由: 某天看到主从复制延时的告警有点频繁,就想着是不是彻底可以解决一下. 一般主从复制,有三个线程参与,都是单线程:Binlog Dump(主) ----->IO Thread (从) - ...

  9. MySQL5.6 基于db的并行复制

    slave的几个类结构:      Master_info:用于IO线程的参数,包括连接master实例的信息.      Relay_log_info:用于sql线程,表示relay log相关的信 ...

随机推荐

  1. ERP项目实施记录11-产品工艺流程图及单据关联图

    借助百度的Echarts做了2个图表,一个展示产品的生产工艺流程,一个展示产品与订单.工程单的关系 上图为产品工艺流程图,鼠标放上去可以显示部件信息 黄色SO图标代表销售订单,单击打开销售订单 红色M ...

  2. 动态规划 hdu 1024

    Max Sum Plus Plus Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others ...

  3. [dev] 刷HHKP的一般流程及常见错误(多图慎点)

    ( 为什么打了个dev的tag?development不用键盘,难道用鼠标??) 嗯呐,我有个HHKP,你看: 好不好看? 脏不脏? 接下来讲一下,我是怎么刷它,要看完哝,不然拆坏了不要怪我. 本来我 ...

  4. Oracle归档开启和更改

    运用 Xshell  客户端工具链接所在的  oracle  服务器 1.先进入数据库里面去 [root@DBSTANDBY ~]# su - oracle [oracle@DBSTANDBY ~]$ ...

  5. Redis的持久化之AOF方式

    AOF方式:将以日志,记录每一个操作 优势:安全性相对RDB方式高很多: 劣势:效率相对RDB方式低很多: 配置: [root@localhost redis]# vi redis.conf 编辑re ...

  6. JSTL将number类型转化为String类型

    <c:set var="lm1"> <c:out value="${lm}" /> </c:set>

  7. opencart3产品页调用upc/数量等信息

    opencart3产品页默认只调用标题.价格.型号等几个数据,如果想要调用更多的参数要如何操作呢?跟着ytkah一起来看看吧.首先打开/catalog/model/catalog/product.ph ...

  8. java框架之SpringBoot(17)-监控管理

    介绍 SpringBoot 提供了监控管理功能的场景启动器,它可以为我们提供准生产环境下的应用监控和管理功能.我们可以通过HTTP.JMX.SSH协议来进行操作,自动得到审计.健康及指标信息等. 使用 ...

  9. Java 基础 多线程和线程池基础

    一,多线程 1.1 多线程介绍 进程:进程指正在运行的程序.确切的来说,当一个程序进入内存运行,即变成一个进程,进程是处于运行过程中的程序,并且具有一定独立功能. 线程:线程是进程中的一个执行单元,负 ...

  10. [LeetCode] 70. Climbing Stairs_ Easy tag: Dynamic Programming

    You are climbing a stair case. It takes n steps to reach to the top. Each time you can either climb ...