05.白话MySQL MVCC

事务特性

大家都知道关系型数据库事务的特性:ACID

image

不同的隔离级别,存在着不同问题
image

MySQL默认的隔离级别是RR(在生产中我们一般采用RC的隔离级别),可以解决脏读和不可重复读,但是不能解决幻读的问题,如果要解决幻读的问题,就要采用串行化的方式,这样对数据库性能会有很大影响。

今天咱们来唠唠隔离性中,MySQL InnoDB实现RC和RR的原理——MVCC

啥是MVCC?

MVCC看起来很熟悉,难道是MVC的表兄弟?开个玩笑,MVCC的英文全称是Multi Version Concurrency Control,中文是多版本并发控制。从名字看来,InnoDB是通过数据行的多个版本,来管理数据库的并发。这个数据行的版本,有点类似于我们开发代码时的多次commit版本。

通过 MVCC 我们可以解决以下几个问题:

  1. 读写之间阻塞的问题,通过 MVCC 可以让读写互相不阻塞,即读不阻塞写,写不阻塞读,这样就可以提升事务并发处理能力。
  2. 降低了死锁的概率。这是因为 MVCC 采用了乐观锁的方式,读取数据时并不需要加锁,对于写操作,也只锁定必要的行。
  3. 解决一致性读的问题。一致性读也被称为快照读,当我们查询数据库在某个时间点的快照时,只能看到这个时间点之前事务提交更新的结果,而不能看到这个时间点之后事务提交的更新结果。

快照读和当前读

快照读

快照读顾名思义,就是读取的快照数据,有可能读到历史版本数据。简单的select都是快照读,比如:

select * from user_info ; 

当前读

当前读就是读取最新数据,而非历史版本,加锁的select或者增、删、改,都属于当前读:

select * from user_info for update;
update user_info set name = 'zhangsan' where id = 2;
delete from user_info where id = 2;
insert into user_info values ('zhangsan');

RC和RR是如何读取数据的呢?

在读已提交和可重复读隔离级别中,多事务并发,查询的并不是当前行最新数据,而是数据库快照。
读已提交隔离级别下,会在每次查询前,读取快照,所以它是不可重复度。
可重复读隔离级别下,只会在事务开始时,查询数据库快照,所以它是可重复读。
那么问题来了,数据库快照是什么?数据库成百上千G的数据,如何能在瞬间生成快照呢?我们继续剖析。

InnoDB中MVCC如何实现的?

在深入MVCC前,我们先做一些知识准备。

事务号

InnoDB会为每个事务分配一个版本号——trx_id,这个版本号是递增的,可以以此判断事务开启的时间。
细心的同学可能会问,如果trx_id用完了怎么办,这里其实大可放心,trx_id的设计可以使用到各位开发者安享晚年,它是采用6字节无符号数据存储,最大值为2的48次方=281474976710656,如果按照每秒10wTPS,可以安全使用89年,既是用到最后一位后,便会从0开始,这样有可能会产生一些脏读,不过基本上不会发生。

行记录的隐藏字段

每个人的身上(数据行)是都有毛毛(隐藏字段)
我来给你唱(分析下)毛毛(隐藏字段)
到底我们身上都有些什么毛(隐藏字段)
我来唱(分析)给你们知道

InnoDB的叶子节点上存储的是数据页,数据页上存储着数据行,行里面存着我们定义的字段,除了我们定义的字段外,还有一些隐藏字段,用于InnoDB系统计算。

image

行数据

image

Undo Log

InnoDB将快照数据,记录在了Undo Log中,我们可以在回滚段中找到相关数据,如图:

image

根据图来看,roll_ptr指针,将undo log用链表结构组合在一起,每个undo log都记录了当时的trx_id,这样我们可以很方便的找到历史快照。

Read View

有了这些前置条件,我们来探讨下,在RC和RR隔离级别下,InnoDB是如何通过MVCC实现一致性读的。
InnoDB中,多个事务对同一行数据更新,会产生多个历史版本(就像git
commit记录一样),这些历史版本就记录在Undo Log中,如果某个事务想要查询某行数据,那它需要读取哪行数据呢?这时候Read View登场了。

image

有了这个read view,我们需要找哪个快照版本的数据,就一目了然了,那到底怎么找,我们看图,一图胜千言:

image

假设当前活跃事务是trx_id_8、trx_id_10、trx_id_12、trx_id_20,那么套用变量:

  1. up_limit_id = trx_id_8
  2. low_limit_id = trx_id_20
  3. trx_ids = [trx_id_8, trx_id_10, trx_id_12, trx_id_20]

假设我们在事务中需要查询的数据的trx_id为x,那么:

  1. x < 8,表示该数据快照是当前活跃事务提交前的版本,是已经完成的事务提交的,安全可以使用。
  2. x > 20,表示该数据快照版本是当前活跃事务之后事务提交的,是不可以使用的。
  3. 若:8 <= x <= 20
    3.1 trx_ids.contain(x),该行数据未提交,不可见。
    3.2 !trx_ids.contain(x),该行数据已提交,可见。

好了,那么通过这种方式,InnoDB实现了全库数据快照,并保证了高并发下数据的准确性和一致性。设计思路不得不佩服。

总结

MVCC的核心可以拆分为MV + VCMV通过Undo Log来实现多版本的管理,VC通过Read View来实现事务并发下,数据是否可见,针对不同的隔离级别,产生Read View的时机也不一样,这样也就实现了不同的隔离级别RC和RR。
MVCC在不通的数据库下,实现的原理不一样,主要是理解设计思想。

完,谢谢大家阅读

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

推荐阅读更多精彩内容