1. LOGICAL_CLOCK 并行复制

1.原理

从MySQL 5.7版本开始,支持LOGICAL_CLOCK级别的并行复制(基于MySQL 5.6的库级别的Group Commit并行复制的大幅改进),通过设置参数slave_parallel_type为LOGICAL_CLOCK来启用(当设置为DATABASE时与MySQL 5.6版本的并行复制相同)。从LOGICAL_CLOCK字面上并不能直观地看出它是基于什么维度来实现并行复制的,下面我们通过解析binlog中记录的内容来进行解读。

mysql lock time out 配置 mysql logical clock_mysql


mysql lock time out 配置 mysql logical clock_数据库底层复制技术_02


从以上对INSERT语句的binlog解析内容来看,从MySQL 5.7 版本开始,新增了两个 事件类型,其中Anonymous_GTID_event用于记录未启用GTID时的binlog 队列信息;

GTID_event用于记录启用GTID时的binlog 队列信息。利用这些binlog 队列信息,从库的 SQL线程在应用主库的binlog时,只要last_committed值相同就可以并行回放,从而大大提高了从库复制的效率。

提示:虽然通过这种方式大幅度提高了从库复制的效率,在一定程度上,并行复制的粒度细化到了事务级别,甚至细化到了行级别(每个事务只修改一行数据),但是可以并行回放的事务必须具有相同的 last_committed值(即使两个事务的数据完全无关,不同last_committed值的事务也不能并行回放),而相同 last_committed值的事务数量多少需要视主库瞬时并发请求的多少而定(当binlog_group_commit_sync_no_delay_count=0时),如果主库没有写压力,写入binlog中的每个事务的 last_committed值都不相同,这个时候从库复制实际上仍然是串行复制。

所以,LOGICAL_CLOCK 级别的并行 复制仍然有一定的优化空间。

2.配置示例

(1)主库

mysql lock time out 配置 mysql logical clock_MySQL并行复制_03

(2)从库

mysql lock time out 配置 mysql logical clock_MySQL并行复制_04

2. WRITESET并行复制

1.原理

在MySQL版本号≥5.7.22和版本号≥8.0.1的版本中,WRITESET并行复制是在 LOGICAL_CLOCK并行复制基础上的演进,引入了基于WriteSet的机制,只要不同事务的不同记录不重叠(通过计算每行记录的hash值来确定是否是相同的记录,该hash值就是writeset值。

WRITESET并行复制本质上就是基于writeset值对如何产生last_committed值做了大幅度优化的),在从库上就可以并行回放。下面我们通过解析binlog中记录的内容来进行解读。

mysql lock time out 配置 mysql logical clock_mysql_05


mysql lock time out 配置 mysql logical clock_数据库复制技术_06

从以上对INSERT语句的binlog解析内容来看,与LOGICAL_CLOCK 并行复制记录的内容相比并没有格式与内容的变化。那么复制的改进点主要是什么呢?

细心的读者可能已经发现了last_committed=2的两个事务的时间戳并不是同一个时刻的,并且在last_committed=2的两个事务之间还夹了一个last_committed=9的事务,这在以往的LOGICAL_CLOCK 并行复制中几乎不可能出现这种情况。发生什么事情了?

对于主库来说,WRITESET并行复制对LOGICAL_CLOCK 并行复制优化的地方并不是在binlog记录的内容格式上,而是在事务写binlog时的last_committed值的计算上。

  • 通过唯一索引或主键索引来区分不同的记录,然后和行记录的库表属性以及数据 属性一起计算hash值(即writeset值),并将计算出的writeset值存放在一个hash表中。
    后续 如果有新事务的行记录计算出的hash值在hash表中无匹配记录,那么新事务不会导致产生 新的last_committed值,即相当于新事务和之前的事务被归并到了同一个binlog 队列中 (即,last_committed值相同);
    后续如果有新事务的行记录计算出的hash值在hash表中找 到了匹配记录,则表示存在事务冲突,产生新的last_committed值(即,产生了一个新的 binlog队列)。
    具体的计算公式为:
    writeset=hash(index_name | db_name | db_name_length | table_name | table_name_length |value | value_length)。
  • 在计算hash值时,如果无法通过索引辨别数据的唯一性,那么将会产生新的 last_committed值。
    对于从库来说,并行应用binlog的逻辑几乎没有变化,仍然根据last_committed值 判断是否可以并行回放。 提示:WriteSet在如下场景中不可用。
  • DDL语句,因为不包含行记录,所以无法生成hash值,也就无法进行比较。
  • session的hash算法和history不同(hash算法被动态修改过之后,遇到不同的算法产 生的值无法进行比较)。
  • 事务更新了被外键关联的字段。

2.配置示例

(1)主库

mysql lock time out 配置 mysql logical clock_数据库底层复制技术_07

(2)从库

mysql lock time out 配置 mysql logical clock_MySQL并行复制_08