最近学习了mysql的各种锁,有点晕,打算通过文章的方式捋一捋。

在学习了mvcc后,我就想,他已经很好的解决了并发读写了,但我也知道innodb提供了多种类型的锁,所以很好奇这些锁有什么用,为什么这些锁的功能是mvcc做不到的?(本文讨论的都是rr级别下的锁)

我先创建一个表,并插入几行数据,如下图:

插入内容如下:

c字段加了普通索引,d字段无索引。

此时,开启session a,开始一个事务,搜索d=5的记录,同时开始session b执行更新操作,session c执行插入操作。

现象:session b 的update和session c的 insert都被阻塞了,注意,并没有直接返回错误。

为什么会被阻塞呢?

因为session a用了select  for update这个锁,是排他锁。

在研究这个排他锁之前,我先从语义上来理解select * from t where d=5 for update的含义。 这句sql的含义是锁住d=5的行吗?也许是的。其实也是的。但是这里有个问题,如果不存在的行,怎么控制呢?session a一次事务中多次执行elect * from t where d=5 for update我们是不是希望得到同样的记录(除非本事务内自己修改)?如果只是锁住了d=5这行,那么session B的update和session C的insert就会在session A的事务进行时插入、更新,这样session a会后面select for update会发现多出来了d=5的行,和第一次不一样,这就破坏了session A锁的声明。这就是幻读。

什么是幻读?

幻读指的是一个事务在前后两次查询同一个范围的时候,后一次查询看到了前一次查询没有看到的行。

在可重复读隔离级别下,普通的查询是快照读,是不会看到别的事务插入的数据的。因此,幻读在“当前读”下才会出现。

上面 session B 的修改结果,被 session A 之后的 select 语句用“当前读”看到,不能称为幻读。幻读仅专指“新插入的行”。

怎么解决呢?

通过上面的讨论我们得知通过给d=5这行加锁是不行的,那么如果我们给所有扫描的记录都加锁能解决这个问题吗?如果这样,update语句会被阻塞,但是insert语句依然可以执行成功,因为insert这行是新的行,我们并没有办法给他加锁。也就是说,即使把所有的记录都加上锁,还是阻止不了新插入的记录

到底如何解决?

接下来,我们再看看 InnoDB 怎么解决幻读的问题。

我们知道行锁只能锁住现有的行,阻止update,但是不能阻止新的行插入,所以innodb引入了间隙锁gap lock,这样在其他session 执行select * for update时,插入操作就会被block。

下图就是六条记录,并且形成了7个间隙,因此有7个间隙锁。

由于d没有索引,所以所有扫描到的行和间隙都会加上锁,此时其他session就不能做任何插入和更新操作了。为了减小锁的粒度,一般需要在索引上做select for update,比如select * from t where c=5 for update。

我们知道,行锁分为读和写两类锁,那么同一个记录写行锁和写行锁是冲突的,这符合行锁的语义。间隙锁呢?不同session的对同一个间隙加锁,会冲突吗?先来分析一下间隙锁的语义,比如(5,10)这个间隙锁,语义是阻止5-10内的插入。所以不同的session对同一个间隙加锁是服务语义的,不冲突。当然也会导致死锁。比如如下顺序操作:

上图的执行顺序会造成死锁:

1、session A先锁住了(5,10),然后session B 也锁住了(5,10)。

2、session B试图插入(9, 9, 9),但是他和session A的间隙锁冲突了,所以会被block

3、接下来session 试图插入(9, 9, 9),和session B的间隙锁冲突,也会被block,就形成了死锁。

间隙锁的引入解决了rr级别下的幻读,但是也导致锁的范围变大了,不同时刻,同一个select 语句可能锁住不同的间隙,的确影响了并发度,但这也是无奈之举。行锁加上间隙锁就是next-key-lock,当select * from t where c=x for update,这个x在表中时就会加next-key-lock。

值得注意的是,只有rr才有间隙锁,读提交的情况下,是不会有间隙锁的,因为提交后必须被读到,隔离性没那么好。

mysql间隙锁_mysql的间隙锁相关推荐

  1. mysql innodb 间隙锁_Mysql innodb 间隙锁

    前段时间系统老是出现insert死锁,很是纠结.经过排查发现是间隙锁!间隙锁是innodb中行锁的一种, 但是这种锁锁住的却不止一行数据,他锁住的是多行,是一个数据范围.间隙锁的主要作用是为了防止出现 ...

  2. mysql suoyin 和锁_Mysql索引与锁

    Mysql索引与锁 Mysql索引与锁 本文以Mysql5.7为例测试. 1:mysql索引方法 Mysql的索引方法分为btree索引和hash索引. hash索引:是通过hash计算后比较,所以只 ...

  3. mysql表级锁和行级锁_MySQL表级锁和行级锁

    一:概述 相对其他数据库而言,MySQL的锁机制比较简单,其最显著的特点是不同的存储引擎支持不同的锁机制.比如,MyISAM和MEMORY存储引擎采用的是表级锁(table-level locking ...

  4. mysql 表级锁_MySQL行级锁和表级锁

    锁定用于确保事务完整性和数据库一致性. 锁定可以防止用户读取其他用户正在更改的数据,并防止多个用户同时更改相同的数据. 如果不使用锁定,数据库中的数据可能在逻辑上变得不正确,而针对这些数据进行查询可能 ...

  5. mysql suoyin 和锁_mysql 索引和锁

    mysql的查询流程一般是:mysql客户端通过协议与mysql服务器建立连接,发送查询语句,先检查查询缓存,如果命中,直接返回结果,否则进行语句解析,有一系列预处理,比如检查语句是否写正确了,然后是 ...

  6. mysql a锁_MYSQL中的锁

    前言 刚开始接触MYSQL,对其锁机制并不了解,在项目里面,针对死锁以及锁竞争,约定了两条规则. 对涉及多个业务表的更新,要遵守一定的顺序,如按照TABLE-A,TABLE-B,TABLE-C的次序 ...

  7. mysql s x锁_mysql 的S 锁和X锁的区别

    共享锁和排它锁 MySQL的锁系统:shared lock和exclusive lock(共享锁和排他锁,也叫读锁和写锁,即read lock和write lock) 读锁是共享的,或者说是相互不阻塞 ...

  8. mysql普通查询排他锁_MySql 共享锁 排他锁

    行级锁是 MySQL 中锁定粒度最细的一种锁,行级锁能大大减少数据库操作的冲突,行级锁分为共享锁和排他锁两种. 共享锁(Share Lock) 共享锁又称读锁,是读取操作创建的锁.其他用户可以并发读取 ...

  9. mysql默认乐观锁悲观锁_MySQL中悲观锁和乐观锁到底是什么?-阿里云开发者社区...

    索引和锁是数据库中的两个核心知识点,隔离级别的实现都是通过锁来完成的 按照锁颗粒对锁进行划分 ? 锁用来对数据进行锁定,我们可以从锁定对象的粒度大小来对锁进行划分,分别为行锁.页锁和表锁. 行锁就是按 ...

  10. mysql中的乐观锁_MySQL中悲观锁和乐观锁到底是什么?

    索引和锁是数据库中的两个核心知识点,隔离级别的实现都是通过锁来完成的 按照锁颗粒对锁进行划分 ? 锁用来对数据进行锁定,我们可以从锁定对象的粒度大小来对锁进行划分,分别为行锁.页锁和表锁.行锁就是按照 ...

最新文章

  1. 据说,程序员已成为女生年度最喜欢男友职业Top3?
  2. 通俗易懂详解Java代理及代码实战
  3. C语言试题五十八之请编写函数fun,:计算并输出下列多项式的值(sn=1+1/1!+1/2!+1/3!+1/4!+…+1/n! )
  4. PHP checkdate()函数与示例
  5. 【STC15库函数上手笔记】4、USART串口
  6. 新修订未成年人保护法6月1日正式实施
  7. 1-1-Html技术
  8. Linux系统C语言遍历系统文件系统,并查询其磁盘使用率(有效磁盘)
  9. 打车应用上马快递业务靠谱吗?
  10. 华为S5300系列交换机V100R005SPH020升级补丁
  11. [转][Python小记] 通俗的理解闭包 闭包能帮我们做什么?
  12. java开发和安卓开发_Android开发和Java开发有什么区别
  13. MapBox本地化部署
  14. c++实现右下角弹窗
  15. linux 进程 网速监控
  16. 如何下载网吧电影服务器上的电影
  17. java版微信三级分销完整源码
  18. Android的虚拟设备的缩写,Android虚拟设备的英语缩写是
  19. 2016 server win 假死_Windows 7假死的几个常见情况以及解决方法
  20. 西门子Wincc/Step7/pcs7

热门文章

  1. 分布式开源调度框架TBSchedule详解
  2. python 绘图中文显示_Python绘图实现显示中文
  3. Python基础:68 个 Python 内置函数介绍(超级详细版本)
  4. Python机器视觉--OpenCV入门--机器视觉与OpencCV用途简介
  5. PLC通过485与单片机通讯示例
  6. java 通过经纬度计算巨鹿,中国主要城市经纬度查询
  7. 开源纯净版u盘安装工具rufus
  8. MySQL基础——DDL语句
  9. Unity2D项目案例及素材
  10. 屏幕录制软件哪个好?