MySQL事务详解(三):脏写与幻读的绝路—锁

在上次MySQL事务详解(二):隔离级别的实现--MVCC的学习中,我们认识到了并发事务访问相同的数据时,
读—写情况下带来的脏读、不可重复读问题,可以通过MySQL的MVCC机制解决。
而对于读—写情况下的幻读问题和写—写情况下的脏写问题,我们提到可以通过MySQL的锁机制解决。

锁的概念

锁的作用于现实生活中的锁的作用类似,都是控制对资源的访问。
而MySQL的锁更侧重于对于资源的并发访问,来保证访问数据的完整性于一致性

锁,其实就是与访问数据关联的一种数据结构。如下图:


当访问(多为修改)一条数据时,首先查询是否有与之关联的数据结构,没有就生成一个,并占有(即加锁成功),如果没有也生成一个并等待(加锁失败)。
当占有锁的事务释放锁之后,等待的事务就会被唤醒执行。


锁的分类

锁的提出是为了解决并发访问带来的问题,但是如果一味的对访问的数据进行加锁,将访问串行化,使其排队等待执行,同时又会降低并发量,降低性能。
因此对锁进行了不同级别的分类,来应对不同的操作场景,如下图:


操作类型

读锁(S锁、共享锁):读取数据用到的锁。给数据加S锁后,其他事务依然可以加S锁(即共享),但是不可以加X锁。
写锁(X锁、排他锁):更改数据用到的锁。给数据加X锁后,其他事务不可以加S锁和X锁(即排他)

态度

乐观锁:假设事务之间很少发生冲突,不主动对数据进行加锁。通常使用版本号时间戳在事务提交时检测是否冲突。
悲观锁与乐观锁相反,假设事务之间经常发生冲突,主动给数据加锁,获取事务所需资源。

粒度

全局锁:对整个数据库实例进行加锁。Flush tables with read lock ,常用于对整个库进行逻辑备份。全局锁对数据库影响较大,锁主库会导致不能更新,业务暂停,锁从库导致主从延迟。
表级锁:对整张表进行锁定,开销小,粒度大,发生冲突的概率高,并发低,可以避免死锁
行级锁:对某一行记录进行锁定,开销大,粒度小,发生冲突概率低,并发高,不能避免死锁
页级锁:对数据库的最小存储单元——页进行锁定,粒度介于表和行之间。应用在BDB存储引擎中,了解即可。

表级锁

表级别的S锁、X锁和元数据锁

# 上锁
lock table tableName read; # 读锁/共享锁
lock table tableName write;# 写锁/排他锁
#解锁
unlock tables; # 客户端断开的时候也会自动释放锁。

使用上面的语言可以为表加上S锁和X锁,以及解锁。

但是如果仅仅是对表进行select、insert、update、delete操作,存储引擎是不会默认为表加上表级锁
而实现这些操作与其他事务中的DDL语句冲突的是表级锁种的元数据锁(MDL)

元数据锁是系统自动控制的,每一条DML、DDL语句执行时都会申请MDL。
DML申请元数据读锁,DDL申请元数据写锁。且DML与DML之间并不相互阻塞,因此DML可以并发执行。
所以表级别的S锁、X锁很少用到。

表级别的意向锁

意向读锁(IS):当我们想向表中的记录加上S锁时,首先给表加上IS锁。
意向写锁(IX):当我们想向表中的记录加上X锁时,首先给表加上IX锁。
IS和IX作用是为了后续给表加上S锁和X锁做的准备工作,避免加上表级别S锁和X锁时,需要遍历所有的数据来判断是否有记录被锁上。

表级别自增锁

自增锁主要是用来给表中声明为AUTO_INCREMENT的字段,在插入记录是递增而用。

  • 在我们不知道要插入的数据量时,例如使用 insert...select;replace...select或者load data时,通常先给表加上一个自增锁,然后生成对应的值,插入完成之后,删除自增锁;
  • 在我们知道具体的插入数据量时,使用轻量级锁,未插入语句生成所需的值后即可释放锁,提高性能。

行级锁

行级锁才是使用最频繁的锁,在开发中遇到的死锁问题一般都是行级锁引起的。
根据不同的情况, 行级锁被分为不同的类型,解决不同的问题,幻读就是其中之一。

行级S锁、X锁

为我们要访问的某一条记录加上读锁或者写锁。S锁与X锁的关系之前已经学习过。

间隙锁

用来解决幻读的锁。因为幻读是在其他事务插入数据后产生,当前事务在第一次select时,数据还不存在。如果使用行级的X锁,找不到上锁的对象。因此提出间隙锁,如下图:

给no=7的数据加上gap锁后,表明在这条数据之前(no为(3,7)间)不能插入新的数据。以此来解决幻读。

临键锁

当我们想锁住访问数据本身以及这条数据之前的间隙时,使用临建锁。即行级SX锁与gap锁的结合。如下图:

插入意向锁

当我们想插入一条数据时,首先要判断插入的位置是有存在gap锁,如果存在就先生成一个插入意向锁,向系统表明有事务在等在插入当前位置。

两种数据读

快照读

MVCC使用的就是快照读,在读取事务是好像拍了一张照片,当前事务读取的是照片快照下的数据。
普通的select 语句都是快照读,不会给记录有加锁操作。

当前读

读取到的数据为最新的的数据。
select ..lock in share mode;对记录加上S锁;
selelct ... for update;对记录加上X锁;
以上两种select语句给记录加上了锁,并且读取到数据是最新的数据。

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

推荐阅读更多精彩内容