简述mysql事务隔离级别、并发与锁

本文是mysql 事务的第二部分-事务的隔离级别与锁。自己不是专职的DBA,理解难免有偏差,只是简单地总结一下。希望对你有所帮助,如果有纰漏,也请留言指出,感谢~
文章主要内容如下:

  • 并发产生的三个经典问题
  • 事务隔离级别介绍
  • 综合:四种隔离级别是如何利用锁解决并发产生的问题的?以及为什么有些情况解决不了

在讲解事务隔离级别之前,我们想讲一下锁与三种并发控制模式,因为在隔离级别这部分会用到。

1 锁

锁,就是将某些资源进行锁定。

1.1 锁的分类

1.1.1 粒度

按照粒度分行锁、表锁、页锁。mysql中 采用的是行锁跟表锁。顾名思义,行锁就是锁定一行资源,表锁就是锁定表。加锁是需要消耗资源的,所以锁的粒度越小,消耗的资源越多,但是并发度越高。

1.1.2 共享

按照是否可以共享,锁又可以分为共享锁(读锁)跟排他锁(写锁)。


共享锁-互斥锁.png
1.1.3 意向锁

意向锁是一种表锁,无需程序员自己加锁,是数据库自动帮添加。
我们用一个例子说明意向锁的用途:

事务A锁住了表中的一行,让这一行只能读,不能写。
之后,事务B申请整个表的写锁。
如果事务B申请成功,那么理论上它就能修改表中的任意一行,这与A持有的行锁是冲突的。
数据库需要避免这种冲突,就是说要让B的申请被阻塞,直到A释放了行锁。
数据库要怎么判断这个冲突呢?
step1:判断表是否已被其他事务用表锁锁表
step2:判断表中的每一行是否已被行锁锁住。
注意step2中通过遍历查询,这样的判断方法效率实在不高,因为需要遍历整个表。

于是就有了意向锁。

意向互斥锁(IX),意向共享锁(IS)是表级锁,不会和行级的X,S锁发生冲突。只会和表级的X,S发生冲突。行级别的X和S按照普通的共享、排他规则即可。

1.1.4 悲观锁与乐观锁

悲观锁就是上文讲的实际的锁,而乐观锁不是真是的锁,而是一种思想。
乐观锁的一种实现方式是通过时间戳来模拟锁。

  • 给每一个事务加一个全局唯一的时间戳。
  • 每个数据项有两个时间戳:读时间戳、写时间戳,分别代表了当前数据被成功执行的的对应事务的时间戳。

当读取数据时,将version字段的值一同读出;
数据每更新一次,对此version值加1。当我们提交更新的时候,判断数据库表对应记录的当前版本信息与第一次取出来的version值进行比对,如果数据库表当前版本号与第一次取出来的version值相等,则予以更新,否则认为是过期数据。

1.2 锁的实现算法

记录锁(Record-Lock)

记录锁是锁住记录的,锁住的是索引记录,而不是我们真正的数据记录

  • 如果锁的是非主键索引,会在自己的索引上面加锁之后然后再去主键上面加锁锁住

  • 如果表上没有索引(包括没有主键),则会使用隐藏的主键索引进行加锁。

  • 如果要锁的没有索引,则会进行全表记录加锁。

间隙锁

间隙锁顾名思义锁间隙,不锁记录。锁间隙的意思就是锁定某一个范围,间隙锁又叫 gap 锁,其不会阻塞其他的 gap 锁,但是会阻塞插入间隙锁这也是用来防止幻读的关键

image
next-key 锁

这个锁本质是记录锁加上 gap 锁。在 RR 隔离级别下(InnoDB 默认),InnoDB 对于行的扫描锁定都是使用此算法但是如果查询扫描中有唯一索引会退化成只使用记录锁。

因为唯一索引能确定行数,而其他索引不能确定行数,需要使用间隙锁防止其他事务中再次添加这个索引的数据造成幻读。RR 隔离级别下,InnoDB 使用 Next-Key Lock 算法避免了幻读。

1.3 死锁

1.3.1 死锁的产生

多个事务之间,彼此持有对方需要的锁,但是又彼此之间不释放,形成了一个资源依赖的环,僵持不下,就形成了死锁。

1.3.2 死锁的预防

主要有2条吧,其实本质就是尽量不要形成资源依赖的环。

  • 1 保证事务间的等待不要出现环,让各个事务都按照一定的顺序为资源加锁。
    *2 如果出现了锁,就是用抢占的方式预防死锁。比如为每个事务加一个时钟,如果时间到了,就继续等或者被抢夺。
1.3.3 死锁的检测与恢复

检查
看是否出现了环。
恢复
按照最小代价的原则,选择一个事务进行回滚,打破环即可。

2 并发产生三个问题

2.1 脏读

脏读是指某个事务读取了另外一个事务没有提交的记录。

2.2 不可重复读

不可重复读是指一个事务连续两次读取某条记录,但是结果不一致。这个过程中主要是另外一个事务对某些记录进行了更新,导致了用相同条件查询时,结果是不一样的。

比如 一个表有id, name,age 三个字段。 当事务A要查询一个name = zp 的记录,在第一次读取的时候(select * from person where id = 1),可能获取到的记录是 (1,“zp”, 1)。但是在事务A准备利用相同条件查询第二次之前,事务B,操作了一条 “将 原本(1, “zp”, 1)的记录 的name改为frank的操作”,那么此时事务A再根据id = 1 查询,此时就查出 (1,“frank”, 1),两次查询的结果是不一样的。此时对于事务A来说,就是不可重复读的。

注意,不可重复读主要是另外一个事务执行了update 的操作,导致第一个事务两次查询不一致。

2.3 幻读

幻读,是指一个事务两次查询的结果不一致。跟不可重复读的区别是其他事务执行了insert操作,导致记录条数变更了
还是以上面的例子讲解一下:
比如 一个表有id, name,age 三个字段。 当事务A要查询一个name = zp 的记录,在第一次读取的时候,可能获取到的记录是 (1,“zp”, 1)。但是在事务A准备利用相同条件查询第二次之前,事务B,执行插入操作 “ 将(3, “zp”, 3)插入表中。”,那么此时事务A再根据name = zp 查询,此时就查出 (1,“zp”, 1), (3,"zp",3) 两条记录,此时对于事务A来说,就发生了幻读。

3 事务隔离级别介绍

InnoDB 支持四种隔离级别。
读未提交、读已提交、可重复读、可串行化。
四种隔离级别能否解决三种并发问题:


隔离级别与并发问题.png

下面一部分,将会讲解各种隔离级别是如何解决并发问题的。

4 四种隔离级别是如何利用锁解决并发产生的问题的?

4.1 隔离级别是怎么解决并发问题的?

总结一句话:隔离界别是靠锁来解决并发问题的。
我们先画个图,更清晰一些:

隔离界别是如何解决并发问题的?.png

注意 可重复读 是对满足条件的所有行,每一行都加了行锁。但是行间其他新插入的行是没有加锁的,所以再插入,就产生了幻读。

图中已经从隔离级别最低到高,是如何一步步解决对应的并发问题的。

如图中所示,通过加Gap锁,可以解决幻读的问题,但是这样整个事务就进入了串行的模式,是单版本的。MySQL中另外一种常见解决幻读问题的方案是多版本并发控制的方式-MVCC.

4.2 利用MVCC 解决并发问题

4.2.1 MVCC的使用场景

虽然锁机制能够从根本上解决并发事务的可串行化的问题,但是在实际环境中数据库的事务大读多写少,如果写请求和读请求之前没有并发控制机制,那么最坏的情况也是读请求读到了已经写入的数据,这对很多应用完全是可以接受的。

在这种大前提下,数据库系统引入了另一种并发控制机制 - 多版本并发控制(Multiversion Concurrency Control)。读写操作之间的冲突就不再需要被关注,而管理和快速挑选数据的版本就成了 MVCC 需要解决的主要问题。

4.2.2 MVCC的机制

写操作:每一个写操作都会创建一个新版本的数据;
读操作:读操作会从有限多个版本的数据中挑选一个最合适的结果直接返回;
版本删除:根据时间戳,会将版本最低,且不再使用的数据定时清除。

5 总结

本文首先讲解了锁、事务隔离级别,以及由并发引起的经典问题。然后重点分析了各个隔离级别是如何利用锁解决并发引起的三类问题的。最后讲了MVCC。

6 参考文献

mysql 共享锁 https://www.jianshu.com/p/e937830bc2de
锁算法 https://www.cnblogs.com/wade-luffy/p/9689975.html#_label1_0
MVCC与锁https://draveness.me/database-concurrency-control

7 其他

本文是mysql学习的第二篇-事务隔离级别、并发与锁,希望对你有所帮助~
如果有疑问,可以直接留言,也可以关注公众号 “链人成长chainerup” 提问留言,或者加入知识星球“链人成长” 与我深度链接~

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

推荐阅读更多精彩内容