事务并发访问情况

读-读 情况

并发事务读取相同的数据,并不会对数据造成影响,允许并发读

写-写 情况

多事务并发写写时会发生

脏写的情况,不过任何一个事务隔离级别都不允许此情况发生,通过

加锁来杜绝脏写

脏写

事务T1 将数据改成了A,但是还

未提交

,可此时事务T2又将数据改成了B,覆盖了事务T1的更改,T1更新丢失,这种情况叫做

脏写

加锁

例如,现在事务T1,T2对这条记录进行并发更改,刚才说是隔离级别是通过加锁来杜绝此脏写的,流程如下 这个锁结构中有两个比较关键的信息(其实还有很多信息,后面再聊)

trx信息:表示这个锁结构是和哪个事务所关联的

is_waiting信息:表示当前事务是否正在等待

事务T1 将数据改成了A,但是还

未提交,可此时事务T2又将数据改成了B,覆盖了事务T1的更改,T1更新丢失,这种情况叫做

脏写

Q:能描述一下两个事务并发修改同一条数据时,mysql这个锁是怎么避免脏写的吗?

A :事务T1在更改这条数据前,就先内存中生成一把锁与此数据相关联(is_waiting为false,代表没有等待),然后咔咔一顿操作更改数据,这个时候,事务T2来了,发现此记录已经有一把锁与之相关联了(就是T1那一把锁),然后就开始等待(is_waiting为true代表正在等待),事务T1更改完数据提交事务后,就会把此事务对应的所结构释放掉,然后检测一下还有没有与此记录相关联的锁,结果发现T2还在苦苦的等待,就把T2的锁结构的(is_waiting为false,代表没有等待)然后把T2事务对应的线程唤醒,T2获取锁成功继续执行,总体流程如上。

读-写 /写-读  情况

在读-写 / 写 -读的情况下会出现脏读,不可重复读,幻读的现象,不同的隔离级别可以避免不同的问题,具体相关内容可以看小杰的这篇文章

不过贴心的我还是列出来了 注:√代表可能发生,×代表不可能发生

隔离级别

脏读

不可重复读

幻读

读未提交(read uncommitted RU)

读提交(read committed RC)

×

可重复读(repeatable read RR)

×

×

串行化(serializable )

×

×

×

但是 RR在某些程度上避免了幻读的发生

怎么避免脏读、不可重复读、幻读这些现象呢?其实有两种方案

方案一 :

读操作使用

MVCC,

写操作进行

加锁

mvcc里面最重要的莫过于ReadView了,它的存在保证了事务不可以读取到未提交的事务所作的更改,避免了脏读。

在RC隔离级别下,每次select读操作都会生成ReadView

在RR隔离级别下,只有第一次select读操作才会生成ReadView,之后的select读操作都复用这一个ReadView

方案二:读写操作都用加锁

某些业务场景不允许读取旧记录的值,每次读取都要读取最新的值。例如银行取款事务中,先把余额读取出来,再对余额进行操作。当这个事务在读取余额时,不允许其他事务对此余额进行访问读取,直到取款事务结束后才可以访问余额。所以在读数据的时候也要加锁

锁分类

当使用读写都加锁这个方案来避免并发事务写-写、读-写、写-读时而产生的脏读,不可重复读,幻读现象时,那么这个锁它就要做到,读读时不相互影响,上面三种情况时要相互阻塞,这时锁也分了好几类,我们继续往下看

锁定读

共享锁(Shared Lock):简称S锁,在事务

要读取一条记录时,需要先获取该记录的

S锁

独占锁(Exclusive Lock):简称X锁,也称排他锁,在事务

要改动一条记录时,需要先获取该记录的

X锁

他们之间兼容关系如下  √代表可以兼容,×代表不可兼容

兼容性

S锁

X锁

S锁

×

X锁

×

×

事务T1获取某记录的S锁后,

事务T2

也可以获取此记录的

S锁,(

兼容)

事务T2

不可以获取此记录的

X锁,直到T1提交后将

S锁释放 (

不兼容)

事务T1获取某记录的X锁后,

事务T2

不可以获取此记录的

S锁,直到T1提交后将

X锁释放 (

不兼容)

事务T2

不可以获取此记录的

X锁,直到T1提交后将

X锁释放 (

不兼容)

锁定读语句

SELECT .. LOCK IN SHARE MODE   # 对读取的记录添加S锁

SELECT .. FOR UPDATE # 对读取的记录添加X锁

多粒度锁

前面提到的锁都是针对记录的,其实一个事务也可以在表级进行加锁(S锁、X锁)

T1给表加了S锁,那么

T2

可以继续获取此表的

S锁

T2

可以继续获取此表中的某些记录的

S锁

T2

不可以继续获取此表的

X锁

T2

不可以继续获取此表中的某些记录的

X锁

T1给表加了X锁,那么

T2

不可以继续获取此表的

S锁

T2

不可以继续获取此表中的某些记录的

S锁

T2

不可以继续获取此表的

X锁

T2

不可以继续获取此表中的某些记录的

X锁

可是怎么可能平白无故的就给表加锁呢,难道没什么条件吗?答案是肯定有条件的

若想

给表加S锁,得先确保

表中记录没有X锁

若想

给表加X锁,得先确保

表中记录没有X锁和S锁

但是这个怎么确保呢?难道要一行一行的遍历表中的所有数据吗?当然不是啦,聪明的大佬们想出了下面这两把锁

意向共享锁(Intention Shared Lock):简称

IS锁,当事务准备在某记录上加S锁时,需要先在表级别加上一个IS锁

意向独占锁(Intention Exclusive Lock):简称

IX锁,当事务准备在某记录上加X锁时,需要先在表级别加上一个IX锁

让我们来看下加上这两把锁之后的效果是什么样子的

当想给记录加S锁时,先给表加一个IS锁,然后再给记录加S锁

当想给记录加X锁时,先给表加IX锁,然后再给记录加X锁

然后 经过上面的操作之后

如果想给表加S锁,先看下表加没加IX锁,如果有的话,则表明此表中的记录有X锁,则需要等到IX锁释放掉后才可以加S锁

如果想给表加X锁,先看下表加没加IS锁或者IX锁,如果有的话,则表明此表中的记录有S锁或者X锁,则需要等到IS锁或者IX锁释放掉后才可以加X锁

这几种锁的兼容性如下表

兼容性

IS锁(表级锁)

S锁

IX锁(表级锁)

X锁

IS锁(表级锁)

×

S锁

×

×

IX锁(表级锁)

×

×

X锁

×

×

×

×

IS、IX锁都是表级锁,他们可以共存。

他们的提出仅仅是为了在之后加表级别的S锁或者X锁时可以快速判断表中的记录是否被上锁,避免用遍历的方式来查看一行一行的去查看而已

InnoDB中的行级锁

Record Lock(记录锁)

官方名字

LOCK_REC_NOT_GAP

仅仅锁住一条记录

有S型和X型之分

Gap Lock(间隙锁)

官方名字

LOCK_GAP

给某记录加此锁后,阻塞数据在此记录和上一个记录的间隙插入,但是不锁定此记录

有S型和X型之分,可是并没有什么区别他们的作用是相同的,

gap锁的作用仅仅是为了防止插入幻影记录而已,如果对一条记录加了gap锁(无论S/X型)并不会限制其他事务对这条记录加Record Lock或者Gap Lock

Next-Key Lock(记录锁+间隙锁)

官方名字

LOCK_ORDINARY

既可以锁住某条记录,又可以组织其他事务在该记录面前插入新记录

Insert Intention Lock(插入意向锁锁)

官方名字

LOCK_INSERT_INTENTION

事务在插入记录时,如果插入的地方加了gap锁,那么此事务需要等待,此时此事务在等待时也需要生成一个锁结构,就是插入意向锁

锁内存结构

我们难道

锁一条记录就要

生成一个锁结构吗?

当然不是!

一个锁结构

如果被加锁的记录符合下面四条状态的话,那么这些记录的锁则会合到一个锁结构中

在同一个事务中进行加锁操作

被加锁的记录在同一个页面中

加锁的类型是一样的

等待的状态是一样的

锁结构信息

然后我们再来依此看下这个所结构每个部分的信息都是什么意思

锁所在的事务信息:无论是表级锁还是行级锁,一个锁属于一个事务,这里记载着该锁对应的信息

索引信息:对于行级锁来说,需要记录一下加锁的记录属于哪个索引

表锁/行锁信息:行级锁

Space_ID:记录所在的表空间 *** Page Number**:记录所在的页号

n_bits:一条记录对应着一个比特;一个页面包含多条记录,用不同的比特来区分到底是那一条记录加了锁,有个计算公式如下(公式中是取商)

n_bits = (1+(n_recs+LOCK_PAGE_BITMAP_MARGIN)/ 8)x 8LOCK_PAGE_BITMAP_MARGIN是固定的值为64,n_recs指当前界面一共有多少条记录(包含伪记录以及在垃圾链表中的记录),

type_mode:32比特的数

lock_mode(锁模式):低4比特位表示

LOCK_AUTO_INC(十进制的4):表示AUTO-INC锁

LOCK_IS(十进制的0):表示共享意向锁,IS锁

LOCK_IX(十进制的1):表示独占意向锁,IX锁

LOCK_S(十进制的2):表示共享锁,也就是S锁

LOCK_X(十进制的3):表示独占锁,也就是X锁

lock_type(锁类型):第5~8比特位表示

LOCK_TABLE(十进制的1):当第5比特位设置为1时,表示表级锁

LOCK_REC(十进制的32):当第6比特位设置为1时,表示行级锁

rec_lock_type(行锁的具体类型):其余的比特位表示

第9比特设置为1时,

表示is_waiting为true,即当前事务获取锁失败,处于等待状态

第9比特设置为0时,

表示is_waiting为false,即当前事务获取锁成功

LOCK_ORDINARY(十进制的0):表示next-key锁

LOCK_GAP(十进制的512):当第10比特位是1时,表示gap锁

LOCK_REC_NOT_GAP(十进制的1024):也就是当第11比特设置为1时,表示Record Lock(记录锁)

LOCK_INSERT_INTENTION(十进制的2048):也就是当第12比特设置为1时,表示Insert Intention Lock(插入意向锁)

LOCK_WAIT(十进制的256):也就是当

其他信息:此文章不讨论

一堆比特位:此文章不讨论

举个例子

事务T1 要给user表中的记录加锁,假设这些记录存储在表空间号为20,页号为21的页面上,T1给id=1的记录加S型Record Lock锁,假如当前页面一共有5条记录(3条用户记录和2条伪记录)

过程:先给表加IS锁,不过我们现在不关心,只关心行级锁, 具体生成的所结构如下图所示

mysql rr gap nextkey_mysql中的各种锁把我搞糊涂啦~相关推荐

  1. mysql中的各种锁把我搞糊涂啦~

    事务并发访问情况 读-读 情况 并发事务读取相同的数据,并不会对数据造成影响,允许并发读 写-写 情况 多事务并发写写时会发生脏写的情况,不过任何一个事务隔离级别都不允许此情况发生,通过加锁来杜绝脏写 ...

  2. 把MySQL中的各种锁及其原理都画出来

    疫情期间在家工作时,同事使用了 insert into on duplicate key update 语句进行插入去重,但是在测试过程中发生了死锁现象: ERROR 1213 (40001): De ...

  3. Mysql数据库中的各种锁

    目录 概述 MyIsam 如何加表锁 并发锁 MyISAM的锁调度 InnoDB 事务(Transaction)及其ACID属性 并发事务带来的问题 InnoDB都有哪些锁? InnoDB的行锁模式及 ...

  4. MySQL中的各种锁(行锁、间隙锁、临键锁等等LBCC)

    目录 1.快照读和锁定读 1.1 一致性读 / 快照读 1.2 锁定读 1.2.1 共享锁和独占锁 1.2.2 锁定读的语句 1.2.2.1 Lock In Share Mode 对记录加S共享锁 1 ...

  5. MySQL/InnoDB中,乐观锁、悲观锁、共享锁、排它锁、行锁、表锁、死锁概念的理解

    MySQL/InnoDB的加锁,一直是一个面试中常问的话题.例如,数据库如果有高并发请求,如何保证数据完整性?产生死锁问题如何排查并解决?我在工作过程中,也会经常用到,乐观锁,排它锁,等.于是今天就对 ...

  6. 一文带你了解 MySQL 中的各种锁机制!

    MySQL中的锁机制,按粒度分为行级锁,页级锁,表级锁,其中按用法还分为共享锁和排他锁. 行级锁 行级锁是Mysql中锁定粒度最细的一种锁,表示只针对当前操作的行进行加锁. 行级锁能大大减少数据库操作 ...

  7. Mysql 事务中Update 会锁表吗?

    Mysql 事务中Update 会锁表吗? 两种情况: 1.带索引 2.不带索引 前提介绍: 方式:采用命令行的方式来模拟 1.mysq由于默认是开启自动提交事务,所以首先得查看自己当前的数据库是否开 ...

  8. mysql 获取距离当前最新的记录_一文带你了解 MySQL 中的各种锁机制!

    云栖号资讯:[点击查看更多行业资讯] 在这里您可以找到不同行业的第一手的上云资讯,还在等什么,快来! MySQL中的锁机制,按粒度分为行级锁,页级锁,表级锁,其中按用法还分为共享锁和排他锁. 行级锁 ...

  9. 一文带你了解MySQL中的各种锁机制!

    云栖号资讯:[点击查看更多行业资讯] 在这里您可以找到不同行业的第一手的上云资讯,还在等什么,快来! MySQL中的锁机制,按粒度分为行级锁,页级锁,表级锁,其中按用法还分为共享锁和排他锁. 行级锁 ...

最新文章

  1. Docker run 命令 参数说明
  2. HDU - 6183 Color it 2017广西邀请赛(线段树)
  3. curl post 日志_curl命令发送Post请求
  4. Windows server 2008 R2实现多用户远程连接
  5. C语言课后习题(35)
  6. 网易身患绝症员工被裁事件背后 年轻一代的辛酸和压力
  7. spark运行wordcount
  8. es修改排序_ElasticSearch自定义排序(转载)
  9. 计算机考研落榜了怎么办,如果,你考研落榜了怎么办?
  10. 一元享移动怎么样_移动推出头条爽卡:9元每月享免流特权,流量1元800M每天
  11. 通俗讲解CDN是什么
  12. C语言输出矩阵的主对角线和以及次对角线和
  13. Windows优化大师已经成为“流氓大师”
  14. 未来10年 人工智能将如何影响淘宝发展?
  15. MySQL数据库—多表查询
  16. 【一头扎进JMS】(4)----RabbitMQ概述
  17. 电力行业人员定位管理解决方案之智能巡检
  18. 使用致远OA系统,打开Excel类型文件,提示office编辑程序未安装
  19. 三星电子 CEO 敲定,三人联席架构继续,李尚勋将任董事会主席
  20. 钛资本研究院:技术周期催生中国风险投资“中生代”

热门文章

  1. 2017.9.18 鬼谷子的钱袋 思考记录
  2. 2017.9.18 数颜色 思考记录
  3. 【英语学习】【WOTD】smithereens 释义/词源/示例
  4. Intel Skylake (Client) 架构/微架构/流水线 (5) - PAUSE指令时延
  5. php搜索所有路线,php包含文件路径查找规则
  6. jq 正则判断邮箱_Python正则15分钟入门
  7. shouldoverrideurlloading为什么有时候不走_为什么付出越多,对方就越不懂得感恩,婚姻有时候也需要斤斤计较...
  8. 阿里云OSS对象存储STS鉴权配置
  9. javascript 公历与农历相互转换工具类
  10. ansible安装和基本使用