MySql MVCC 机制底层原理

1.文章适用对象:

能够基本描述清楚mysql事务隔离级别 不可重复去或可重复读的现象,想进一步探讨底层设计思想的人

2.什么是MVCC

MVCC (Multi-Version Concurrency Control) (注:与MVCC相对的,是基于锁的并发控制,Lock-Based Concurrency Control)是一种基于多版本的并发控制协议,只有在InnoDB引擎下存在。MVCC是为了实现事务的隔离性,通过版本号,避免同一数据在不同事务间的竞争,你可以把它当成基于多版本号的一种乐观锁。当然,这种乐观锁只在事务级别未提交锁和已提交锁时才会生效。MVCC最大的好处,相信也是耳熟能详:读不加锁,读写不冲突。在读多写少的OLTP应用中,读写不冲突是非常重要的,极大的增加了系统的并发性能。具体见下面介绍。


3.可重复读现象

我们有表,account, 分别开启 五个事务,隔离级别为可重复读, 如下图,  问: 红色部分 name的执行结果 是什么?


如果你的回答和下图一致 则表示 对mysql 可重复读理解没有问题?


4.MVCC的实现机制

InnoDB在每行数据都增加三个隐藏字段

1. 一个 6字节的 DB_TRX_ID 字段 即:通常在其他文章中看到的 事务id

2.一个7字节的 DB_ROLL_PTR 字段 即:通常范围以回滚指针

3.一个 6字节的 DB_ROW_ID 字段, 该字段在当前事务自增,主要是确定当前数据id (本文章中不涉及该字段)

具体详见 mysql  官方描述

注意: 一般在讲解mvcc 的文章中不提及第三个字段,请大家大家鉴别式阅读


4. MVCC 底层原理

4.1 事务id

  首先我们说明一下 mysql 事务id 的生成时机, 当我们开启一个事务的时候,并不会立刻生成事务id ,而是执行 增删改的时候才会生成 id ,事务id 累加.

解析:

1. 我们在前三个事务开始  都执行了一个不相干的 update ,保证 事务id 生成

2. 为了保证文章的可读性,我们分别把 事务id 记录为 100,200,和300

3. 最后两列因为开启事务后,没有执行 增删改 所以不会有事务id生成

如下图:


4.2 Read-View

当我们开启一个select 的事务时 (例如上图第四列), mysql 底层会在第一次执行select 时 生成一个 read-view ,它是 由当前所有 未提交的事务id + 已提交事务id 的最大值组成

例如 在 上图中 ① 的位置 , 此时 mysql 地城会生成一个 read-view =[100,200],300 ,同时 在该事务中一单read-view 生成,该事务的read-view 将不会改变,除非事务提交.


解析如下图


可以预见: 最后一列的事务的read-view =[200],300


4.3 undo log

当我们执行 增删改时 其实并不是 真的把之前的数据删除了,而是 使用日志记录到了 undo log 中.

insert 操作, 底层会把记录先写入 undo log 中,提交时在写入对应的空间

delete,底层并不会会把记录直接删除,而是把原来的数据复制一份到 undolog 中,并记录一个删除字段为true (不属于文章开头说的三个字段)

对于update 操作,如果我们对同一条数据进行了多次更新操作,则 在undo log 中将存在多分他们之间用DB_ROLL_PTR 字段 关联 如下图:


通过undo log这种机制 mysql 保证了不同的事务可以重复读取 事务开始时的数据状态

数据可视性原则

上面提到, 当进行增删改时 ,原来的数据并不会删除undo log 中 存放了很多 "待提交数据",那么当我们查询时底层是怎么决定哪些数据显示,哪些不显示呢? 我们来聊一下 mysql mvcc的显示规则

首先, mysql 把数据分为三种状态

注意: 下图的早晚指的是 生成read-view 的时间/或者生成事务id 的时间 ,不是 执行 begin transaction; 的时间


显示数据的显示规则很明确

1. 当前事务开启时已经提交的数据, 对当前事务的查询是可以查询到的 (灰色部分)

2. 比当前事务开启晚的事务提交的数据,对当前事务的查询是不可见的(灰色部分)

3. 比当前事务开启的早,但是数据在当前事务开启前并未提交, 这部分数据对当前事务不可见

4, 事务自己提交的数据,自己可见

我们不禁要问 : 底层是如何划分的呢?

这里我们对 read view 做一个 概念上的划分,

min_trx_ids:  我们把  readview 生成时所有未提交的 事务id  叫做 min_trx_ids(是一个数组),

max_trx_ids: readview 生成时系统中最大的事务id  叫做max_trx_ids

creator_trx_id: 把当前事务的id 叫做creator_trx_id

如下图:


有了这些概念, mysql 底层 是按照如下的规则判断事务的可见性的.

1.如果被访问版本的trx_id属性值与ReadView中的creator_trx_id值相同,意味着当前事务在访问它自己修改过的记录,所以该版本可以被当前事务访问。

2.如果被访问版本的trx_id属性值小于ReadView中的min_trx_id值,表明生成该版本的事务在当前事务生成ReadView前已经提交,所以该版本可以被当前事务访问。

3.如果被访问版本的trx_id属性值大于ReadView中的max_trx_id值,表明生成该版本的事务在当前事务生成ReadView后才开启,所以该版本不可以被当前事务访问。

4.如果被访问版本的trx_id属性值在ReadView的min_trx_id和max_trx_id之间,那就需要判断一下trx_id属性值是不是在m_ids列表中,如果在,说明创建ReadView时生成该版本的事务还是活跃的,该版本不可以被访问;如果不在,说明创建ReadView时生成该版本的事务已经被提交,该版本可以被访问。

总结:

mysql mvcc 底层通过 比对 read-view 中的事务id 来判断 undolog中的 数据对当前事务是否可见

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容