mysql 冲突检测_MYSQL MGR 学习,冲突检测,certification

certification介绍

certification的作用为MYSQL多MASTER时,事务的冲突检测,也是MGR与之前的半同步复制的主要区别,在commit,写binlog之前加入了certify步骤(冲突检测),解决多MASTER时,可能导致数据不一致的问题。

0b35fafcf37f38b99dd663b2f28c04dc.png

我们考虑下面3个事务,T1,T2,T3,同时更新id=1 and c=0的记录, 如果在单库上执行由innodb完成事务冲突处理,事物一致性,是没有问题的

8ea271fd12f9cd879c201e72a8a549d9.png

但如果在MYSQL多MASTER部署,T1,T2,T3分别在别不同的实例上执行,三个事务产生的冲突innodb就无能为力了,最3个事务执行完成后,c值为多少?

由于commit之后才能会binlog同步到其它库,三个update都可以执行成功,都更新了记录,但commit如果都能成功,三个事务都认为自己更新成功了,那么就产生了不一致的数据。

MGR 中 certification就是要解决这种问题。实际上T1,T2,commit会失败。

36d52fe079f3a6af9b690955d9a1bea7.png

T1,T2 commit报错如下

ERROR 1180 (HY000): Got error 149 - ‘Lock deadlock; Retry transaction’ during COMMIT

certification实现

GTID分配

普通主从复制,GTID分配是 server_uuid:id(number)

MGR GTID分配与普通主从复制不同,每个mgr组统一分配 group_replication_group_name(uuid):id(number)

冲突检测的单位

冲突检测的最小单位为行(暂时这么理解,不一定准确)

怎么唯一标识行?

索引名称+db名+db名长度+表名+表名长度+构成索引唯一性的每个列的值+值长度

所以使用MGR必须有主键

MGR的冲突检测

MYSQL 乐观执行,在事务执行时认为不会发生冲突,在commit时才会检查冲突,并最终完成(持久化)事务操作。

以上面的例子进行说明

00:00 T1 UPDATE ID=1的行,执行成功,ID=1 时间戳00:00

00:01 T2 UPDATE ID=1的行,执行成功,ID=1 时间戳00:00

00:02 T3 UPDATE ID=1的行,执行成功,ID=1 时间戳00:00

00:03 T3 COMMIT成功,ID=1的最终事务修改时间戳为00:03 ID=1 时间戳00:03

00:04 T1 COMMIT时,发现我00:00修改的数据,已经修其它事务修改(早于ID=1 时间戳00:03),操作的是旧的数据,发生冲突,回滚。

00:04 T1 COMMIT时,发现我00:01修改的数据,已经修其它事务修改(早于ID=1 时间戳00:03),操作的是旧的数据,发生冲突,回滚。

当然MYSQL MGR中实现的时间戳并不是时间,(多个节点中的时钟不同怎么办),MGR使用逻辑事务时间,dml或commit时的gtid_executed

使用gtid_executed 作为事务时间(执行事务之前获取当前的gtid_executed作为事务戳 snapshot version),进行示例(对group name(uuid)进行了简化)

00:00 T1 UPDATE ID=1的行,执行成功,ID=1 gtid_executed snapshot 1a55cda2:1-10

00:01 T2 UPDATE ID=1的行,执行成功,ID=1 gtid_executed snapshot 1a55cda2:1-10

00:02 T3 UPDATE ID=1的行,执行成功,ID=1 gtid_executed snapshot 1a55cda2:1-10

00:03 T3 COMMIT成功,ID=1的最终事务修改时间戳为00:03 ID=1 commit gtid_executed 1a55cda2:1-11

00:04 T1 COMMIT时,发现修改ID=1的记录snapshot gtid_executed 1a55cda2-9e7c-11ea-ae57-080027db8b10:1-10 是 commit gtid_executed 1a55cda2-9e7c-11ea-ae57-080027db8b10:1-11的真子集,也就是操作的数据是旧数据,发生冲突,回滚。

00:04 T1 COMMIT时,发现修改ID=1的记录snapshot gtid_executed 1a55cda2-9e7c-11ea-ae57-080027db8b10:1-10 是 commit gtid_executed 1a55cda2-9e7c-11ea-ae57-080027db8b10:1-11的真子集,也就是操作的数据是旧数据,发生冲突,回滚。

0e102e1737282e9994933814a07f79f0.png

certification_info

Certification_info是数据库状态机复制协议的核心组件。它实现了基于certification procedure实现冲突检测。

1、用于全局事物分配,Snapshot Isolation 给满足认证且可以提交给组中所有成员的事务分配逻辑时间戳,事务id。

2、是一个单调递增的计数器,在组中的所有成员中都是相同的。gtid_execute

3、用于生成snapshot version,还用于更新认证信息。

4、将事务中的数据行映射到事务在执行时看到的gtid_execute,即transaction snapshot version(事务在哪个版本上执行)

5、认证时事务携带的snapshot version,与certification_info中的进行比较,如果传入的snapshot version,是相同write set的已经certified transaction的子集,则认为当前 transaction在过期数据之上执行,认证失败。否则,此事务将被标记为certified并进入applier。同时更新Certification_info

typedef std::unordered_map<:string gtid_set_ref> Certification_info;

write set(一组可以并应用,不会冲突的事务的集合),XXHASH64[索引名称+db名+db名长度+表名+表名长度+构成索引唯一性的每个列的值+值长度]

MAP(XXHASH64[索引名称+db名+db名长度+表名+表名长度+构成索引唯一性的每个列的值+值长度] Gtid_set)

13fcf65195de0b3a304374bf4cd3fed6.png

certification_info的清理

certification_info始终保存在内存中,随着事务的执行,certification_info会越来越大,占用大量内存,且影响认证效率,需要及时清理

当certification_info 中的snapshot version小于所有已经开始的事务,则可以被清理,因为事务的snapshot version>certification_info中的snapshot version,不会产生冲突。

清理规则待更新…

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值