当前位置: 首页 > news >正文

Writeset

优质博文:IT-BLOG-CN

MySQLWriteSet功能主要用于增强复制的并发性和一致性,特别是在主从复制环境中。WriteSetMySQL 5.7引入的一个特性,主要用于解决复制过程中可能出现的写冲突问题。

MySQL并行复制目前经历过三个比较关键的时间结点“库间并发”,“组提交”,“写集合”;

一、库间并发

库间并发:一个实例内可能会有多个库schema,不同的库之间没有什么依赖关系,所以在slave那边为每一个库schema单独起一个SQL线程,这样就能通过多线程并行复制的方式来提高主从复制的效率。

这个理论听起来没问题,但是事实上一个实例也就一个业务库,所以这种库间并发就没什么作用了;也就是说这个方式的适用场景比较少,针对这个不足直到“组提交”才解决!

二、组提交

组提交:如果多个事务他们能在同一时间内提交,这个就间接说明了这个几个事务锁上是没有冲突的,也是就说他们各自持有不同的锁,互不影响;逻辑上我们几个事务看一个组,在slave以“组”为单位分配给SQL线程执行,这样多个SQL线程就可以并行跑了;而且不在以库为并行的粒度,效果上要比“库间并发”要好一些。

这个事实上也有一些问题,因为它要求库上要有一定的并发度,不然就有可能变成每个组里面只有一个事务,这样就有串行没什么区别了,为了解决这个问题MySQL提供了两个参数就是希望在提交时先等一等,尽可能的让组内多一些事务,以提高并行复制的效率。

binlog_group_commit_sync_no_delay_count设置一个下水位,也就是说一个组要凑足多少个事务再提交;为子防止永远也凑不足。那么多个事务MySQL还以时间为维度给出了另一个参数binlog_group_commit_sync_delay这个参数就是最多等多久,超过这个时间长度后就算没有凑足也提交。

这两个参数特别难找到合的值,就算今天合适,过几天业务上有点变化后,又可能变的不合适了;如果MySQL能自己达到一个自适应的效果就好了;这个自适用要到WriteSet才完成(WriteSet并不是通过自动调整这两个参数来完成,它采用了完全不同的解决思路)。

三、WriteSet

WriteSet解决了“组提交”的问题

案例:假如第一天更新id=1的数据,第二天更新了id=2的数据,第三天有个slave同步数据了,以“组提交”的特点,这两个更新会被打包到不同的“组”,也就是说会有两个组;由于每个组内只有一个事务,所以逻辑上就串行起来了。

身为DBA可以看出来这两个事实上是可以打包到同一个组里来的,因为他们互不冲突,就算打包到同一个组也不引起数据的不一致。 于是你有两个办法:
【1】将binlog_group_commit_sync_no_delay_count设置成2,也就是说一个组至少要包含两个事务,并且把binlog_group_commit_sync_delay设置成24小时以上!如果你真的做了,你就可以回家了,你的数据库太慢了(第一条update等了一天),才完成!
【2】MySQL用一本小本子记下它最近改了什么,如果现在要改的数据和之前的数据不冲突,那么他们就可以把包到同一个组;刚才的例子,由于第二天改的值的id=2所以它和第一天的不冲突,那么它完全可以把第二天的更新和第一天的更新打包到同一个组。这样组里面就有两个事务了,在slave第三天回放时就会有一种并行的效果。

binlog_transaction_dependency_history_size这个参数可以设置小本子的容量了;mysql-5.7.22之后的版本小本子就是它生来就有的。

只要在master上新增两个参数开启writeSet

binlog_transaction_dependency_tracking  = WRITESET                 #    COMMIT_ORDER          
transaction_write_set_extraction        = XXHASH64
binlog_transaction_dependency_history_size = 500000

binlog_transaction_dependency_tracking这个参数用于配置二进制日志中事务依赖关系的跟踪方式。它的主要目的是提高从库的并行复制能力。可选值:
【1】COMMIT_ORDER:基于提交顺序的事务依赖跟踪。这是默认值,表示从库按照主库上事务的提交顺序来执行事务。
【2】WRITESET:基于写集的事务依赖跟踪。启用这个选项后,MySQL会生成每个事务的写集,并在从库上进行冲突检测,以允许并行执行不冲突的事务。
【3】WRITESET_SESSION:基于写集的事务依赖跟踪,但在会话级别进行。与WRITESET类似,但冲突检测仅在同一会话内进行。

transaction_write_set_extraction这个参数用于配置写集提取的算法。写集提取是生成事务写集的过程,主要用于冲突检测。可选值:
【1】OFF:禁用写集提取。这是默认值。
【2】XXHASH64:使用XXHASH64算法进行写集提取。XXHASH64是一种快速的非加密哈希算法,适用于高性能场景。

binlog_transaction_dependency_history_size是内存中保存的做冲突检测的数据行数量的上限值,该值越大,保存的数据行越多,事务间冲突检测后并发度越高。

实际上Writeset是一个集合,使用的是C++ STL中的set容器,在类Rpl_transaction_write_set_ctx中包含了如下定义:

std::set<uint64> write_set_unique;

集合中的每一个元素都是hash值,这个hash值和我们的transaction_write_set_extraction参数指定的算法有关,其来源就是行数据的主键和唯一键。每行数据包含了两种格式:
【1】字段值为二进制格式
【2】字段值为字符串格式

四、实现细节

【1】生成WriteSet 当一个事务在主库上提交时,MySQL会扫描事务中的所有写操作(如INSERTUPDATEDELETE),并将这些操作涉及的键生成一个WriteSet

假设我们有一个简单的事务,它在一个表users上执行了一些写操作:

START TRANSACTION;
INSERT INTO users (id, name) VALUES (1, 'Alice');
UPDATE users SET name = 'Bob' WHERE id = 2;
DELETE FROM users WHERE id = 3;
COMMIT;

在这个事务中,涉及的写操作包括一个插入操作、一个更新操作和一个删除操作。MySQL会生成一个WriteSet来表示这些操作涉及的键。

WriteSet示例:假设users表的主键是id,那么生成的WriteSet可能会包含以下信息:

INSERT 操作:插入了 id = 1 的记录。
UPDATE 操作:更新了 id = 2 的记录。
DELETE 操作:删除了 id = 3 的记录。

简化后的WriteSet可以表示为:

WriteSet = { (users, id, 1), (users, id, 2), (users, id, 3) }
WriteSet = { (users, id, 1), (users, id, 2), (users, id, 3) }

这里的(users, id, 1)表示在users表中主键为1的记录。

在实际实现中,WriteSet可能会使用更复杂的数据结构和算法来存储和处理这些信息。例如,MySQL可能会使用哈希表或其他高效的数据结构来存储这些键,并使用哈希算法(如XXHASH64)来生成键的哈希值。

【2】传播WriteSet 生成的WriteSet会随着二进制日志binlog一起传播到从库。在从库上,MySQL会解析这些日志并提取出WriteSet

【3】冲突检测和处理: 从库在执行事务前,会检查当前事务的WriteSet是否与正在执行的其他事务的WriteSet有冲突。如果有冲突,当前事务会被推迟执行,直到冲突消除。

冲突检测:当从库接收到这个事务时,它会使用WriteSet来进行冲突检测。假设从库上有另一个事务正在执行,它的WriteSet是:

WriteSet = { (users, id, 2), (users, id, 4) }

从库会检测两个WriteSet是否有交集。在这个例子中,两个WriteSet都有 (users, id, 2),说明存在写冲突。因此,从库会推迟执行这个事务,直到冲突消除。

五、WriteSet实践

我们要执行的目标SQL如下

create database tempdb;
use tempdb;
create table person(id int not null auto_increment primary key,name int);insert into person(name) values(1);
insert into person(name) values(2);
insert into person(name) values(3);
insert into person(name) values(5);

看一下组提交对上面SQL的分组情况

last_committed(组号)sequence_num(组内id)SQL语句
11create database tempdb
22create table person(id int not null auto_increment primary key,name int)
33insert into person(name) values(1)
44insert into person(name) values(2)
55insert into person(name) values(3)
66insert into person(name) values(5)

write_set的对“组提交”优化后的情况

last_committed(组号)sequence_num(组内id)SQL语句
11create database tempdb
22create table person(id int not null auto_increment primary key,name int)
33insert into person(name) values(1)
34insert into person(name) values(2)
35insert into person(name) values(3)
36insert into person(name) values(5)

可以看到各个insert是可以并行执行的,所以它们被分到了同个组last_committed相同。

last_committedsequence_number这两个值在binlog里面记着就有,我在解析binlog的时候习惯使用如下选项

mysqlbinlog -vvv --base64-output='decode-rows' mysql-bin.000002

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • vue选项式写法项目案例(购物车)
  • 操作系统week3
  • vue源码分析(九)—— 合并配置
  • 打印机问题故障处理_十大打印机故障大全及处理方法
  • 大模型各版本Base, Chat, Instruction 之间的区别
  • Leetcode 3298. Count Substrings That Can Be Rearranged to Contain a String II
  • Pandas Series 概述与使用指南
  • [SDX35+WCN6856]SDX35 + WCN6856 默认增加打包wifi配置hostapd_24g.conf和hostapd_5g.conf操作方法
  • linux中vim编辑器的应用实例
  • Python画笔案例-058 绘制单击画酷炫彩盘
  • 第三篇 第16章 工程量清单计价
  • 大数据-144 Apache Kudu 基本概述 数据模型 使用场景
  • vitis2022.2生成动态设备树
  • Linux——应用层协议HTTP
  • 格力嵌入式面试题及参考答案
  • 收藏网友的 源程序下载网
  • [nginx文档翻译系列] 控制nginx
  • 【407天】跃迁之路——程序员高效学习方法论探索系列(实验阶段164-2018.03.19)...
  • angular学习第一篇-----环境搭建
  • CSS相对定位
  • download使用浅析
  • express + mock 让前后台并行开发
  • JDK9: 集成 Jshell 和 Maven 项目.
  • PHP CLI应用的调试原理
  • Vultr 教程目录
  • Webpack 4 学习01(基础配置)
  • 初识 beanstalkd
  • 开放才能进步!Angular和Wijmo一起走过的日子
  • 开年巨制!千人千面回放技术让你“看到”Flutter用户侧问题
  • 利用DataURL技术在网页上显示图片
  • 每个JavaScript开发人员应阅读的书【1】 - JavaScript: The Good Parts
  • 如何设计一个比特币钱包服务
  • 使用 Xcode 的 Target 区分开发和生产环境
  • 我与Jetbrains的这些年
  • # centos7下FFmpeg环境部署记录
  • (3)(3.2) MAVLink2数据包签名(安全)
  • (编译到47%失败)to be deleted
  • (三)Honghu Cloud云架构一定时调度平台
  • (轉)JSON.stringify 语法实例讲解
  • .bat批处理(十):从路径字符串中截取盘符、文件名、后缀名等信息
  • .naturalWidth 和naturalHeight属性,
  • .NET 3.0 Framework已经被添加到WindowUpdate
  • .net core 3.0 linux,.NET Core 3.0 的新增功能
  • .NET Core 将实体类转换为 SQL(ORM 映射)
  • .net6 当连接用户的shell断掉后,dotnet会自动关闭,达不到长期运行的效果。.NET 进程守护
  • .Net开发笔记(二十)创建一个需要授权的第三方组件
  • .NET企业级应用架构设计系列之应用服务器
  • /etc/sudoers (root权限管理)
  • ::
  • [ SNOI 2013 ] Quare
  • [20150629]简单的加密连接.txt
  • [2018-01-08] Python强化周的第一天
  • [ASP.NET 控件实作 Day7] 设定工具箱的控件图标
  • [BZOJ2208][Jsoi2010]连通数
  • [C/C++随笔] char与unsigned char区别