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

并发复制(Parallel Replication 系列三:MySQL 5.7 MariaDB 10parallel replication对比

作者:沃趣科技MySQL数据库工程师  麻鹏飞


经过上两篇关于MySQL/MariaDB 的Binary Log Group Commit的发展历程和enhanced multi-threaded slave的介绍,相信大家对MySQL 基于Binay Log 的replication的原理以及为了解决主备数据复制延迟问题而引入的enhanced multi-threaded slave 功能,支持从库多线程并发回放主库提交的事务有了更深入的了解。同时为了更好的发挥MySQL 5.7/MariaDB 10 并发复制的性能,两个版本都在主库Binary Log Group Commit的阶段做了更加深入的优化。

无论是MySQL还是MariaDB在Binary Log Group Commit优化的目的都是:使高并发下的事务尽可能的在同一个时间点提交,然后用一次fsync()的操作将这一组的Binary log缓存的数据写入磁盘。当并发事务可以在同一个时间提交,说明每个线程所执行的事务之间没有锁冲突(如果有锁冲突,并发的事务将无法在同一个时刻提交),那么意味着这一组并发提交的事务在slave机器上能并发重放主库提交的事务,所以我们只需要在master机器对二进制日志进行Group Commit的时候标记上组提交相关信息,slave机器就可以安全的并发执行主库提交的事务。

我们来看一个例子:

事务T1、T2(start transaction)开始事务,落后于事务T3、T4的(start transaction)开始时间,但是这一组事务都在C(commit)时间点提交事务,所以这一组事务(T1、T2、T3、T4)将在master机器上进行Binary Log group Commit,然后该二进制日志推送到slave机器上时可以并发执行这一组被标记的事务。

原理:

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

      在上一篇文章提到过:MySQL/MariaDB开启Binary Log日志后使二进制日志写入顺序和存储引擎提交顺序保持一致,Binary Log Group Commit分为三个过程:

图1: Binary Log Group Commit 三个阶段

在 Flush stage:所有已经注册线程都将写入binary log缓存

在Sync stage :binary log缓存的数据将会sync到磁盘,当sync_binlog=1时所有该队列事务的二进制日志缓存永久写入磁盘

在 Commit stage:    leader根据顺序调用存储引擎提交事务。

那么为了使更多的并发线程事务能够视为在同一个时刻commit即在Sync阶段(调fsync()把binary log文件系统缓存日志永久刷入磁盘文件)master机器标记并发提交的事务为同一组事务的信息写入binary log日志中。我们可以在Flush Stage将注册为leader的线程带领更多的follower线程到Sync stage进行一次fsync()的操作,来增加Binary Log Group Commit的数量。

如下图:

当前MySQL/MariaDB数据库实例上运行三个线程分别提交T1、T2、T3事务,T1事务的线程率先提交进入第一阶段Flush stage队列,发现该队列是空队列故注册成leader,与此同时T2事务进入Flush stage成为该队列的follower等待leader调配,事务T1的leader带领T2事务进入Sync stage进行一次fsync()操作那么T1、T2在binary log进行一次group commit。
       在二进制日志内标记了这一组事务。之后T3线程的事务随后进入了binary log提交的过程。

2: 组提交过程

MariaDB 10通过@@binlog_commit_wait_count and @@binlog_commit_wait_usec 两个参数设置,既事务commit阶段的时候至少等binlog_commit_wait_usec毫秒直到有binlog_commit_wait_count个数时进行一次组提交,来提高每组事务中的事务数量,并可以通过查询状态变量@@binlog_commit和@@binlog_group_commit来查参数来查看当前binary log group commit比例。

MySQL5.7通过引入 binlog_group_commit_sync_delay和 binlog_group_commit_sync_no_delay_count参数即提高binary log组提交并发数量,既MySQL等待binlog_group_commit_sync_delay毫秒的时间直到binlog_group_commit_sync_no_delay_count个数时进行一次组提交。

实现:

Binary Log Group Commit在MySQL 5.7和MariaDB 10 中是默认开启不需要配置任何信息,且在binary log中标记的组提交信息依赖于GTID,而MySQL和MariaDB的GTID组成和实现方式不一样,这里我们简单梳理下。

在MySQL 5.7版本由于Binary Log Group Commit是默认开启的,所以即使你不开启gtid_mode在配置文件中,binary log的内容中同样也有GTID 信息只不过标记的信息是"ANONYMOUS"

>    show binlog events in 'mysql-bin.000004';截取一段信息

1.  ...............
| mysql-bin.000004 | 3571 | Anonymous_Gtid |     15112 |        3636 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'          |

2.  | mysql-bin.000004 | 3636 | Query          |     15112 |        3712 | BEGIN                   |

3.  | mysql-bin.000004 | 3712 | Rows_query     |     15112 |        3763 | # INSERT INTO t1 () VALUES ()                 |

4.  | mysql-bin.000004 | 3763 | Table_map      |     15112 |        3807 | table_id: 108 (db2.t1)                        |

5.  | mysql-bin.000004 | 3807 | Write_rows     |     15112 |        3847 | table_id: 108 flags: STMT_END_F               |

6.  | mysql-bin.000004 | 3847 | Xid            |     15112 |        3878 | COMMIT /* xid=33 */                           |
.................

>     mysqlbinlog -vvv mysql-bin.00004 | less

1.  #151231 14:34:03 server id 15112  end_log_pos 2408 CRC32 0x5586fe71     Anonymous_GTID  last_committed=6        sequence_number=8

2.  SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;

3.  # at 2408

4.  #151231 14:34:03 server id 15112  end_log_pos 2484 CRC32 0x748efb17     Query   thread_id=11    exec_time=0     error_code=0

5.  SET TIMESTAMP=1451543643/*!*/;

6.  BEGIN

7.  ..

MariaDB的GTID同样也是默认开启且GTID是由Domain ID、Server ID和transaction Sequence Number组成:

   图3 MariaDB GTID组成

>    show binlog events in 'mysql-bin.000003';截取一段信息

1.  .......
| mysql-bin.000003 |  335 | Gtid              |     15102 |         377 | BEGIN GTID 0-15102-64139                      |

2.  | mysql-bin.000003 |  377 | Table_map         |     15102 |         434 | table_id: 18 (test.sbtest1)                   |

3.  | mysql-bin.000003 |  434 | Write_rows_v1     |     15102 |         657 | table_id: 18 flags: STMT_END_F                |

4.  | mysql-bin.000003 |  657 | Xid               |     15102 |         688 | COMMIT /* xid=16 */                           |

5.  | mysql-bin.000003 |  688 | Gtid              |     15102 |         732 | BEGIN GTID 0-15102-64140 cid=20               |

6.  | mysql-bin.000003 |  732 | Table_map         |     15102 |         789 | table_id: 19 (test.sbtest6)                   |

7.  | mysql-bin.000003 |  789 | Write_rows_v1     |     15102 |        1012 | table_id: 19 flags: STMT_END_F                |

8.  | mysql-bin.000003 | 1012 | Xid               |     15102 |        1043 | COMMIT /* xid=20 */                           |

9.  | mysql-bin.000003 | 1043 | Gtid              |     15102 |        1087 | BEGIN GTID 0-15102-64141 cid=20               |

10. | mysql-bin.000003 | 1087 | Table_map         |     15102 |        1145 | table_id: 20 (test.sbtest12)                  |

11. | mysql-bin.000003 | 1145 | Write_rows_v1     |     15102 |        1368 | table_id: 20 flags: STMT_END_F                |

12. | mysql-bin.000003 | 1368 | Xid               |     15102 |        1399 | COMMIT /* xid=21 */                           |
......

>    mysqlbinlog -vvv mysql-bin.00003  | less

1.     .......

2.     # at 1754

3.  #160104 15:16:46 server id 15102  end_log_pos 1798 CRC32 0x26104c0b     GTID 0-15102-64143 cid=20 trans

4.  /*!100001 SET @@session.gtid_seq_no=64143*//*!*/;

5.  BEGIN

6.  /*!*/;

7.  # at 1798

8.  #160104 15:16:46 server id 15102  end_log_pos 1856 CRC32 0x2c994f5a     Table_map: `test`.`sbtest12` mapped to number 20

9.  # at 1856

10. #160104 15:16:46 server id 15102  end_log_pos 2079 CRC32 0x02b5a694     Write_rows: table id 20 flags: STMT_END_F

11.

12.  BINLOG '

13.  .........

结论:

MySQL 5.7 / MariaDB 10的parallel replication都是基于主库上Binary Log Group Commit。

MySQL:  主库并发提交的事务group commit写入binary log日志中,当事务被标记的  last_committed=N的值相同时(通过binlog_group_commit_sync_delay、 binlog_group_commit_sync_no_delay_count参数设置提高并发事务数量),可以在slave节点并发回放主库提交的事务。

MariaDB: 主库并发提交的事务group commit写入binary log日志中,当事务被标记的 cid=N 的值相同时(通过 binlog_commit_wait_count、binlog_commit_wait_usec参数设置提高并发事务数量),可以在slave节点并发回放主库提交的事务。

Reference:http://geek.rohitkalhans.com/2013/09/enhancedMTS-deepdive.html

MySQL并发复制系列三:MySQL和MariaDB实现对比的更多相关文章

  1. MySQL并发复制系列二:多线程复制

     http://blog.itpub.net/28218939/viewspace-1975822/ 并发复制(Parallel Replication) 系列二: Enhanced Multi-th ...

  2. MySQL并发复制系列二:多线程复制 2016

    并发复制(Parallel Replication) 系列二: Enhanced Multi-threaded Slaves作者:沃趣科技MySQL数据库工程师  麻鹏飞 首先梳理下传统MySQL/M ...

  3. mysql并发复制系列 一:binlog组提交

    http://blog.itpub.net/28218939/viewspace-1975809/ 作者:沃趣科技MySQL数据库工程师  麻鹏飞 MySQL  Binary log在MySQL 5. ...

  4. MySQL并发复制系列一:binlog组提交 (转载)

    http://blog.csdn.net/woqutechteam/article/details/51178803 MySQL  Binary log在MySQL 5.1版本后推出主要用于主备复制的 ...

  5. MySQL 并行复制演进及 MySQL 8.0 中基于 WriteSet 的优化

    MySQL 8.0 可以说是MySQL发展历史上里程碑式的一个版本,包括了多个重大更新,目前 Generally Available 版本已经已经发布,正式版本即将发布,在此将介绍8.0版本中引入的一 ...

  6. MySQL学习笔记——〇三 MySQL习题

    在前面讲了MySQL的初步使用方法以后,在这里放出来一些案例来看看怎么做. 先看看database的结构,一共5个表 外键关系: class的cid是student的class_id的外键,teach ...

  7. java并发编程系列三、Lock和Condition

    有了synchronized为什么还要Lock? 因为Lock和synchronized比较有如下优点 1. 尝试非阻塞地获取锁 2. 获取锁的过程可以被中断 3. 超时获取锁 Lock的标准用法 p ...

  8. 【转】哦,mysql 的其它发行版本Percona, mariadb

    原文:http://geek.csdn.net/news/detail/130146 2016年11月25日,沃趣科技"智慧应用 数据先行"2016产品发布会暨新三板挂牌庆祝会在杭 ...

  9. 浅谈MySQL Replication(复制)基本原理

    1.MySQL Replication复制进程MySQL的复制(replication)是一个异步的复制,从一个MySQL instace(称之为Master)复制到另一个MySQL instance ...

随机推荐

  1. C语言指针5分钟教程

    指针.引用和取值 什么是指针?什么是内存地址?什么叫做指针的取值?指针是一个存储计算机内存地址的变量.在这份教程里“引用”表示计算机内存地址.从指针指向的内 存读取数据称作指针的取值.指针可以指向某些 ...

  2. Web自动化框架之五一套完整demo的点点滴滴(excel功能案例参数化+业务功能分层设计+mysql数据存储封装+截图+日志+测试报告+对接缺陷管理系统+自动编译部署环境+自动验证false、error案例)

    标题很大,想说的很多,不知道从那开始~~直接步入正题吧 个人也是由于公司的人员的现状和项目的特殊情况,今年年中后开始折腾web自动化这块:整这个原因很简单,就是想能让自己偷点懒.也让减轻一点同事的苦力 ...

  3. 【C++对象模型】构造函数语意学之二 拷贝构造函数

    关于默认拷贝构造函数,有一点和默认构造函数类似,就是编译器只有在[需要的时候]才去合成默认的拷贝构造函数. 在什么时候才是[需要的时候]呢? 也就是类不展现[bitwise copy semantic ...

  4. 【转】Yahoo!团队:网站性能优化的35条黄金守则

    Yahoo!的 Exceptional Performance团队为改善 Web性能带来最佳实践.他们为此进行了一系列的实验.开发了各种工具.写了大量的文章和博客并在各种会议上参与探讨.最佳实践的核心 ...

  5. Python学习之eventlet.greenpool

    该模块提供对 greenthread 池的支持. greenthread 池提供了一定数量的备用 greenthread ,有效限制了孵化 greenthread 过多导致的内存不足,当池子中没有足够 ...

  6. Chapter4:表达式

    左值和右值 当一个对象被用作右值的时候,用的是对象的值(内容),当对象被用作左值的时候,用的是对象的身份(在内存中的位置). 一个重要的原则是需要右值的地方可以用左值来代替,但是不能把右值当作左值使用 ...

  7. CreateThread函数&&CString::GetBuffer函数

    对这个两个常见的windows下的函数学习了一下: //最简单的创建多线程实例 #include <stdio.h> #include <windows.h> //子线程函数 ...

  8. Java每日一则-001

    Java中类名与文件名的关系 1.Java保存的文件名必须与类名一致: 2.如果文件中只有一个类,文件名必须与类名一致: 3.一个Java文件中只能有一个public类: 4.如果文件中不止一个类,文 ...

  9. GUI、模块化与结对编程(homework-03)

    摘要: 在本次作业博客里,我将主要阐述作业3的收获.作业3表面是将之前的程序转换为图形界面(之前程序见http://www.cnblogs.com/shone/p/3348372.html),然而本质 ...

  10. Java设计模式系列之命令模式

    命令模式(Command)的定义 将一个请求封装为一个对象,从而可用不同的请求对客户进行参数化:对请求排队或记录日志,以及支持可撤销的操作,将”发出请求的对象”和”接收与执行这些请求的对象”分隔开来. ...