Mysql MVCC原理和锁详解

一、什么是MVCC?

  MVCC(Multi-Version Concurrency Control)多版本并发控制,是确保在高并发下,多个事务读取数据时不加锁也可以多次读取相同的值。MVCC在读已提交(READ COMMITTED)、可重复读(REPEATABLE READ 简称RR)模式下才生效。

二、MVCC解决了事务的什么问题?

在并发事务下,可能会产生如下问题:
1.脏读 :当前事务读取到其它事务未提交的数据。
2.脏写 : 事务B提交后,将事务A提交的数据覆盖。
3.不可重复读:在同一个事务中,不同时间段执行相同的查询语句,得到的结果集不相同。
4.幻读:事务A读取到了事务B新增的数据。

MVCC可重复读模式下,解决了事务的脏读、脏写、不可重复读等问题,但是还是存在幻读问题,幻读问题可以使用间隙锁进行解决。

三、MVCC的实现原理

3.1 undo log文件

  MVCC是通过历史操作快照的版本链进行实现的,这个版本链实际上就是undo log的记录的数据。
  undo log里面通过两个隐藏字段trx_id、roll_pointer将这些数据串联起来,形成一个历史版本链。当事务需要回滚或事务需要执行select语句时,都是通过undo log里面的roll_pointer去查找对应版本的数据。

3.2 read view一致性视图

  当事务要执行查询sql时,会生成一个一致性视图,也就是read view,read view由当前所有未提交的事务ID组成的一个数组,和已创建的最大事务id构成。
  在这个数组中,最小的事务id称为min_id,最大的事务id称为max_id,当要查询历史数据时,需要通过对比事务的id才能区分哪些版本的数据可以展示,哪些数据不能展示。
示例:read view = [100,101],300;
其中,Min_id = 100、Max_id = 300。100和101都属于未提交的活跃事务。

在可重复读模式下,只会在第一次执行查询语句时生成read view,而在读已提交模式下,每次查询都会生成一个read view。

3.3 redo log 版本链对比规则

Mysql将整个版本链的数据划分为三个区间:

数据区间

如果trx_id < min_id,那么表示这个事务是属于已提交的事务,数据是可见的。
如果trx_id > max_id,那么标识这个事务是属于将来要开启的,数据是不可见的。
如果min_id <= trx_id <= max_id ,就要分为两种情况:
  a.如果trx_id在read view数组中,那么就表示当前trx_id属于未提交的事务,数据是不可见的。
  b.如果trx_id不在read view数组中,那么当前trx_id就是属于已提交的事务,数据是可见的。

  正是有了MVCC机制,让多个事务对同一条数据进行读写时,不需要加锁也不会出现读写冲突。事务A每次读的都是历史版本的快照,而事务B修改的数据,则会称为这个版本链的最新数据,通过上面的对比规则,其它事务是不会读取到最新的已修改的值。
  但是MVCC没有解决幻读问题,对于其它事务新增的数据,虽然读不到,但是仍然可以感知到新增的数据,比如对新增数据进行修改操作。在可重复读模式下,可以使用间隙锁进行解决幻读问题。

3.4 间隙锁 Gap Lock

间隙锁可以理解成范围锁,锁的是两个值之间的范围,其它事务无法对范围内的数据进行新增和修改。
比如事务A当前的间隙锁的值是7-10,但是目前数据库中并不存在id =8的数据,事务B想要新增id =8的数据,此时是无法新增的,这样就可以解决幻读问题。

四、数据库中的锁

4.1 数据库的锁是什么?

在并发场景下,锁是协调并发访问资源的一种手段,通过加锁阻塞方式,让一个资源在同一时刻只能有一个客户端去访问。

4.2 锁的分类

a.从性能上分
悲观锁:对要访问的资源直接加锁
乐观锁:通过版本对比的方式来实现,不会对访问的资源加锁
b.从操作类型分
读锁(shared 共享锁):针对同一行数据,可以允许多个读,但是会阻塞写锁。
写锁(exclusive 排它锁):对于同一行数据,会阻塞其它事务的读和写。
c.从锁的粒度上分
表锁:开销小、加锁快,不会出现死锁问题,锁的粒度大,并发度低。
行锁:开销大、加锁慢,会出现死锁问题,锁的粒度小,并发度高。
一句话总结:读锁不会阻塞读,会阻塞写;写锁会阻塞读写
行锁:InnoDB中的行锁是加在索引上的,不是针对数据行进行加锁。如果该索引失效,行锁会升级成表锁。

五、总结

MVCC:
1、MVCC在不加锁的情况下,解决了并发事务的脏读、脏写不可重复度等问题,而幻读可以使用间隙锁进行解决。
2、undo log里面通过两个隐藏字段trx_id、roll_pointer将历史快照数据串联起来,形成一个版本链,是read view获取数据的前提。
3、read view是在第一次查询时生成的,由所有未提交的活跃事务id组成的数组和最大事务id构成。
4、通过对比事务id的大小,将数据进行展示。

锁:
InnoDB中,行锁是加在索引上,因此要注意索引的失效问题,否则行锁升级成表锁。
尽量减少条件检索范围,避免间隙锁的范围过大,降低并发力度。

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

推荐阅读更多精彩内容