mysql:innodb存储引擎 事务隔离级别与mvcc

1. 事务隔离级别

四种隔离级别及对应问题的可能性。

隔离级别 脏读 不可重复读 幻读
读未提交 可能 可能 可能
读已提交 不可能 可能 可能
可重复读 不可能 不可能 可能
串行化 不可能 不可能 不可能

2. 快照读(非锁定读, 普通select语句)

一致性非锁定读是通过MVCC来读取数据库中对当前事务而言可读版本中最新数据。在查询时,有其他事务正在完成写入,那么不会等待行锁的释放,而是读取旧一点版本的数据。

2.1 undo log

innodb中,当事务提交时,需要先将该事务的所有操作日志写入到重做日志文件,然后等提交操作完成,事务才算完成。这里的重做日志文件包含了两部分:redo log和undo log。 redo log被用来保证事物的持久性,undo log用来帮助实现事务回滚和MVCC。这里重点讲一下undo log, 当事务回滚时,利用undo逻辑地将数据库恢复到之前的状态。
那么如何通过undo 来回滚和实现MVCC呢。 聚簇索引记录中都包含两个必要的隐藏列:

  • trx_id:每次对某条聚簇索引记录进行改动时,都会把对应的事务id赋值给trx_id隐藏列。
  • roll_pointer:每次对某条聚簇索引记录进行改动时,都会把旧的版本写入到undo日志中,然后这个隐藏列就相当于一个指针,可以通过它来找到该记录修改前的信息。
聚簇索引trx_id和roll_pointer

每次对记录进行改动时,生成对应的undo log, undo log中同样有roll pointer,指向了更早的一个版本。于是就形成了一个链表。


版本链

事务回滚时,逻辑地删除该版本链中对应trx_id的数据就行了。

2.2 MVCC

  • read uncommitted级别下, 直接读取版本链中的头节点就好了。

  • read committed级别下, MVCC在每个select执行时,先创建一个read view。 read view 包含了以下信息:

    • 当前事务id: cur_trx_id
    • 当前系统中最小的活跃事务id: min_active_trx_id
    • 当前系统中最大事务id: max_trx_id
      通过read view,可以确定哪些事务写入的数据是本次select可读的:readable_trx = (0, min_active_trx_id) U (min_active, max_trx_id)区间内非活跃的事务 U 当前事务
      select读取时,通过版本链,读取出trx_id在readable_trx中且版本最新的记录,作为返回值。由于读取的要么是已提交事务的写入,要么是当前事务的写入,因此避免了脏读,然而由于每次select都会生成read view, 可读取版本可能会不同,因此无法避免不可重复读。
  • repeatable read 级别下, 在事务中的第一个select时,去创建read view。确定当前事务中select的可读版本。之后每次select时,都根据该read view 去读取可读且版本最新的数据。从而保证了该事务中的可重复读。

  • serializable级别下,串行化,那么就无法通过版本连来控制了。读加共享锁,写加排他锁,读写互斥。

3. 当前读(锁定读)

在RC和RR隔离级别下,快照读总是在当前事务中先创建read view,然后读出可读版本的最新数据。然而在某些场景下,我们希望的是,在当前事务中要读取数据时,如果有其他事务正在写入与查询相关的数据,我们先等他写入完成,提交后获取到读取的机会,然后读出写入后的最新数据。这种模式下,快照读就无能为力了。这是一个很典型的读写问题,innodb为了解决这种问题,采用了读写锁的解决办法。

  • read uncommitted级别下, 读写均不互斥,假设事务b,更新某条记录,此时事务a 去select for update/ in share mode, 由于未作任何同步互斥, 此时事务a即可读取到b对数据的写入,如果事务b回滚,那么可能带来很多负面的影响。
  • read committed级别下锁定当前记录。脏读是由于一个事务中对数据的写入,在提交之前被另一个事务读取到。那么解决思路就是写入时对该数据加X锁,读取时根据需要加S锁(select ... in share mode)或者X锁(select ...for update)。也就是所谓的record lock。假设数据库内有非聚簇索引[1,3, 5, 5, 5, 7 ], 事务a在读取索引为5的记录时加record lock,此时另一个事务b想要修改索引为5的数据,发生阻塞。直到事务a提交事务,释放锁之后,事务b继续执行才能访问。
    但是RC级别下,无法解决幻读的问题,假设事务b是要插入一条索引为5的记录,根据b+树,它可以在(3,5), 5,(5,7)之间的任何位置进行插入,此时仅仅锁住了5这个点,那么仍然可以在(3,5),(5,7)两个区间的中间插入。
image.png
事务a 事务b
begin; begin;
select count(1) from xx where sec_id = 5; (结果:3)
insert into xxx set ... sec_id =5
commit
select count(1) from xx where sec_id = 5; (结果:4)
...

repeatable read级别下,使用next-key lock的方式对索引加锁,对非唯一索引而言,它不仅锁住记录本身(record lock),而且还对(3,5), (5,7)两个区间加锁(gap lock)。最终的效果就是,在(3,7)区间内的任何写入,都将被阻塞。对于唯一索引而言,只需要锁住当前记录本身即可,因此next-key-lock降级为record lock。因此锁定读下的RR级别,避免了幻读的问题。

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

推荐阅读更多精彩内容