217_mysql_复制技术_多线程复制

举报
alexsully 发表于 2021/11/11 19:12:38 2021/11/11
【摘要】 多线程复制和多线程回放

二阶段提交背景

本意就是将事务分成两个阶段提交,了保证redolog和binlog数据的安全一致性 (XID 是否相同)
两阶段提交的第一阶段 (prepare阶段):写redo-log 并将其标记为prepare状态
紧接着写binlog
两阶段提交的第二阶段(commit阶段):写bin-log 并将其标记为commit状态


当MySQL写完redolog并将它标记为prepare状态时,并且会在redolog中记录一个XID,它全局唯一的标识着这个事务。
而设置`sync_binlog=1`时,做完了上面第一阶段写redolog后,mysql就会对应binlog并且会直接将其刷新到磁盘中binlog结束的位置上也有一个XID

只要这个XID和redolog中记录的XID是一致的,MySQL就会认为binlog和redolog逻辑上一致。就上面的场景来说就会commit,
而如果仅仅是rodolog中记录了XID,binlog中没有,MySQL就会RollBack

MySQL增加了binlog的组提交,目的同样是将binlog的多个刷盘操作合并成一个,结合Redo log本身已经实现的 组提交,

分为三个阶段(Flush 阶段、Sync 阶段、Commit 阶段)完成binlog 组提交

1 Flush阶段

首先获取队列中的事务组

将Redo log中prepare阶段的数据刷盘(图中Flush Redo log)

将binlog数据写入文件,当然此时只是写入文件系统的缓冲,Flush阶段队列的作用是提供了Redo log的组提交

 

2 Sync 阶段

为了增加一组事务中的事务数量,提高刷盘收益,MySQL使用两个参数控制获取队列事务组的时机:

    binlog_group_commit_sync_delay=N:在等待N μs后,开始事务刷盘(图中Sync binlog)

    binlog_group_commit_sync_no_delay_count=N:如果队列中的事务数达到N个,就忽视binlog_group_commit_sync_delay的设置,直接开始刷盘

3 Commit 阶段

 首先获取队列中的事务组,依次将Redo log中已经prepare的事务在引擎层提交

Commit阶段不用刷盘,Commit阶段队列的作用是承接Sync阶段的事务,完成最后的引擎提交

mysql> show global variables like '%group_commit%';

binlog_group_commit_sync_delay 表示binlog刷盘前,binlog提交需要等待的微秒数。
0表示提交后立即刷盘
非0值表示允许多个事务的日志一起提交刷盘,即组提交。
此参数为0并不代表组提交被关闭,组提交是默认开启的,此参数的最大值为1s,即1000000微秒。

binlog_group_commit_sync_no_delay_count:
参数表示在binlog_group_commit_sync_delay等待时间内,如果事务数达到此参数指定的值,则会触发一次组提交。
如果达到延迟时间但并未达到此参数设置的事务数限制的话,也会进行一次组提交。

六 多线程复制

5.6之前,从库不支持多线程复制, 但是innodb存储引擎本身支持 group commit, 同时为了保证数据一致性,启用了二阶段提交

6.1 Database 多线程复制

允许并行回放的粒度是数据库级别, 同一时刻修改数据且修改是不同数据库,才允许并行回放;系统变量的配置

主库 
 Slave_parallel_type = DATABASE
 从库
 slave_parallel_workers = N 
 Slave_parallel_type = DATABASE

对从库的改动,传统SQL线程,增加了SQL协调器线程(coordinator线程),具体执行回放任务的是 worker线程

6.2 logical_clock多线程复制

 基于database 多线程复制颗粒度仍然很粗,只要事务之间不冲突,即使同一时间修改同一个数据库, 也允许并行回放  slave_parallel_type = logical_clock

  • Last_commited: 表示事务在每个binlog文件中的 Binlog Group编号,会重复,表示可以并行回放;
  • last_commited值是主库事务进入prepare阶段获取已提交的事务的最大sequence_number,称为事务的commit-parent, 如果两个事务的commit-parent相同,可以并行回放
  • Sequence_number 表示每个binlog中的事务编号; 不会重复

5,7新增两个event

  •         Anonymous_gtid_log_event 用于记录未启用GTID binlog group
  •         Gtid_log_event 用于记录启用GTID binlog group

系统变量的配置

主库 
 Slave_parallel_type = logical_clock
 
 从库
 slave_parallel_workers = N 
 Slave_parallel_type = logical_clock
 slave_preserve_commit_order =1
 # 参数在多线程复制环境下,能够保证从库回放relay log事务的顺序与这些事务在relay log中的顺序完全一致,
也就是与主库提交的顺序完全一致(可能会有些许的等待)

6.3 WRITESET 多线程复制

        在大于5.7.22版本和8.0.1 版本中对 logical_clock多线程复制的优化,只要不同事务的修改不重叠,就可以在slave中 并行回放, 通过计算每行记录的 hash值,来确定其是否为相同的记录。该hash值就是WRITESET值

背景

  • 1 WRITESET 多线程复制对 LOGICAL_CLOCK 多线程复制的优化 不是在binlog格式上,而是在事务写binlog时对last_commited值的计算做了优化
  • 2 logical_clock颗粒度为事务, 默认COMMIT_ORDER依赖模式下, 主库生成只有同一时间提交的事务生成的last_commited值才相同,
  • 3 不同时间生成的事务也有不存在锁冲突的可能,所以last_commited值也应该相同
  • 4 引入新机制 – WRITESET = hash(index_name, db_name, db_name_length, table_name, table_name_length, value, value_length)
  • 5 通过唯一索引/主键索引来区分不同记录, 然后和行记录的库表属性以及数据属性一起计算hash值,存hash
  • 6 后面的新事物的行记录计算出hash值在表中无匹配,那么不会新生成last_commited 归属到同一个binlog group, 既新旧事务last_commited值相同
  • 7 后面的新事物行记录计算出hash 值,如果匹配到hash 表,说明事务有冲突,需要新last_commited值,即产生新的binlog group

6.4 writeset多线程场景

  • binlog_transaction_dependency_tracking是设在主库,可以取commit_order,writeset,writeset_session,主要是控制binlog文件中last_committed的计算方式
  • commit_order: group commit,同在prepare阶段的事务,在binlog中last_committed数值一样,传到从库之后可以并行执行
  • writeset: 会对事务处理的行数据哈希出一个writeset值,放到一个哈希表里,如果两个事务先后提交,但是处理的行数据没有冲突,即wirteset不一样,就可以有同样的last_committed,在从库可以并行执行;
  • writeset_session,比writeset多了一个约束,同一个session的事务,在binlog里保留先后顺序,也就是last_committed按先后顺序递增。
  • slave_preserve_commit_order是设在从库,控制从库并行reply时事务提交的顺序

DDL 语句

  • 事务更新了被外键关联的字段
  •  如果短平快事务,writeset, writeset_session 没有比默认的commit_order 提高太多
  • 如果大事物居多,commit_order,binloglast_commiited值重复率不高, writeset & writeset_seesion重复率高,提高效率多 (本身大事物不可取-worker线程是瓶颈)

配置

主库 
 Slave_parallel_type = logical_clock
 transaction_write_set_extraction = XXHASH64
 binlog_transaction_dependency_tracking = WRITESET | WRITESET_SESSION
 binlog_transaction_dependency_history_size = 25000
 检测当前全局已提交事务的 write_set 是否已经超过了 binlog_transaction_dependency_history_size 设置的值,如果超过,则清空已提交事务的全局 write_set
 
 从库
 slave_parallel_workers = N 
 Slave_parallel_type = logical_clock
 slave_preserve_commit_order =1 
#参数在多线程复制环境下,能够保证从库回放relay log事务的顺序与这些事务在relay log中的顺序完全一致,也就是与主库提交的顺序完全一致(可能会有些许的等待)
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。