InnoDB的MVCC机制

在讲解InnoDB的MVCC机制之前,我们应该了解MySQL所支持的事务,以及各个事务级别的区别和每一个事务级别所存在的问题。

1. 事务

事务必须保证ACID,而ACID表示原子性、一致性、隔离性和持久性

1.1 事务的隔离级别

事务可以通过start transaction语句开始一个事务,然后要么使用commit提交事务将所修改的数据持久保存,要么使用rollback撤销所有修改

1.1.2 READ UNCOMMITTED (未提交读 RU)

在READ UNCOMMITTED级别,事务中的修改,即使没有提交,对其他事务也都是可见的。事务可以读取未提交的数据,这也被称为脏读

1.1.3 READ COMMITTED (提交读 RC)

大多数的数据库系统的默认隔离级别都是READ COMMITTED(MySQL 不是)。READ COMMITTED满足前面提到的隔离级别的简单定义:一个事务开始时,只能“看见” 已提交的事务所做的修改。换句话说,一个事务从开始知道提交之前,所做的任何修改对其他事务都是不可见的。这个级别也叫不可重复读,因为在同一事务内执行两次相同的查询,可能会得到不一样的结果。

例子: 当事务的隔离级别在RC级别的时候,事务A和事务B同时对数据D操作,当事务A开始的时候,读取的数据D保存下来了,这是事务B也在修改数据D,并且先于事务A提交。这是事务A再读数据D的时候,就会出现前后不一致情况,这就是所谓的不可重复读。

1.1.4 REPEATABLE READ (可重复读 RR)

这是MySQL的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。不过理论上,这会导致另一个棘手的问题:幻读 (Phantom Read)。简单的说,幻读指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影” 行。InnoDB和Falcon存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决了该问题。

例子:mysql的默认事务隔离级别是RR级别的,同样是上述例子,当时不同的是当事务A和事务B开始的时候,都保存一份自己的快照,每一份快照中都有数据D的值,所以这样在同一事务中,无论重读读多少次都是正确的。

例子:在RR级别中,可能出现幻读。同样是上述例子,事务A和事务B同时查询数据D,事务A发现数据D为空,就想插入数据,但是这是事务B已经插入了数据D并且已经提交。这时事务A的提交就会出错。这是因为事务A的写操作是当前读操作。

1.1.5 SERIALIZABLE (可串行化 S)

这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。

隔离级别 脏读可能性 不可重复可能性 幻读可能性 加锁读
READ UNCOMMITTED Yes Yes Yes No
READ COMMITTED No Yes Yes No
REPEATABLE READ No No Yes No
SERIALIZABLE No No No Yes

2. MVCC机制

InnoDB的一致性的非锁定读就是通过在MVCC实现的,Mysql的大多数事务型存储引擎实现的都不是简单的行级锁。基于提升并发性能的考虑,它们一般都同时实现了多版本并发控制(MVCC)。MVCC的实现,是通过保存数据在某一个时间点的快照来实现的。因此每一个事务无论执行多长时间看到的数据,都是一样的。所以MVCC实现可重复读。

  • 快照读:select语句默认,不加锁,MVCC实现可重复读,使用的是MVCC机制读取undo中的已经提交的数据。所以它的读取是非阻塞的
  • 当前读:select语句加S锁或X锁;所有的修改操作加X锁,在select for update 的时候,才是当地前读。

RR隔离级别下的快照读,不是以begin开始的时间点作为snapshot建立时间点,而是以第一条select语句的时间点作为snapshot建立的时间点。

2.1. MVCC依赖数据

行记录隐藏字段

  • db_row_id,行ID,用来生成默认聚簇索引(聚簇索引,保存的数据在物理磁盘中按顺序保存,这样相关数据保存在一起,提高查询速度)
  • db_trx_id,事务ID,新开始一个事务时生成,实例内全局唯一
  • db_roll_ptr,undo log指针,指向对应记录当前的undo log
  • deleted_bit,删除标记位,删除时设置

undo log

  • 用于行记录回滚,同时用于实现MVCC


    图片1.png

2.2 操作方式

  1. update
  • 行记录数据写入undo log,事务的回滚操作就需要undo log
  • 更新行记录数据,当前事务ID写入db_trx_id,undo log指针写入db_roll_ptr
  1. delete
  • 和update一样,只增加deleted_bit设置
  1. insert
  • 生成undo log
  • 插入行记录数据,当前事务ID写入db_trx_id, db_roll_ptr为空

这样设计使得读操作很简单,性能很好,并且也能保证只会读到符合标准的行,不足之处是每行记录都需要额外的储存空间,需要做更多的行检查工作,以及额外的维护工作

2.3 MVCC如何实现RR

  • RR定义:在一个事务内同一快照读执行任意次数,得到的数据一致;且只能读到第一次执行前已经提交的数据或本事务内更改的数据
  • 原理:对符合查询条件的记录进行可见性判断就是那些数据本事务可以看见,那些数据看不见
  • read view:记录当前处于活动状态的所有事务ID,RR级别下,第一次快照读时创建,RC级别下,每次快照读均会创建新的
  • 缺点: 可能出现幻读
图片2.png
图片3.png

3 总结

在事务隔离级别为RC和RR级别下, InnnoDB存储引擎使用的才是多版本并发控制。然而,对于快照数据的定义却不相同。在RC事务隔离级别下,对于快照数据(undo端数据),总是读取被锁定行的最新的一份快照数据。而在RR事务隔离级别下,对于快照数据,多版本并发控制总是读取事务开始时的行数据。

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

推荐阅读更多精彩内容