MySQL的意向共享锁、意向排它锁和死锁


Posted in MySQL onJuly 15, 2022

一、InnoDB的表级锁

在绝大多数情况下应该使用行锁,因为事务和行锁往往是选择InnoDB的理由,但个别情况下也使用表级锁。

事务需要更新大部分或全部数据,表又比较大,如果使用默认的行锁,不仅这个事务执行效率低,而且可能造成其他事务长时间等待和锁冲突事务涉及多个表,比较复杂,很可能引起死锁,造成大量事务回滚

我们希望获取表锁时,执行以下命令:

MySQL的意向共享锁、意向排它锁和死锁

在使用表锁的时候,涉及的效率问题:
要获取一张表的共享锁S或者排它锁X,首先要确定这张表没有被其它事务获取过X锁,这张表里面的数据没有被其它事务获取过行锁X锁。

假如我们这张表有一千万个数据,怎么判断这一千万个数据哪些行有X锁?
如果想获得表的S锁,就需要判断表里面哪些行有过X锁,如果有一些行有过X锁,那么就不能获取这张表的S锁或者X锁。除了挨个检查,没有更好的办法,这就导致效率低下的问题

由于需要加表锁而去挨个遍历数据,确定是否有某些数据被加了行锁,而导致的效率低下问题。我们这里学习的意向共享锁和意向排他锁就可以解决,当要获取表的X锁是,不需要再检查表中的哪些行锁被(X或者S)占用,只需要快速检查IX和IS锁即可

二、意向共享锁和意向排它锁

  • 意向共享锁(IS锁):事务计划给记录加行共享锁,事务在给一行记录加共享锁前,必须先取得该表的IS锁
  • 意向排他锁(IX锁):事务计划给记录加行排他锁,事务在给一行记录加排他锁前,必须先取得该表的IX锁

MySQL的意向共享锁、意向排它锁和死锁

  • 在加行锁之前,由InnoDB存储引擎加上表的IS或IX锁
  • 意向锁之间都是兼容的,不会产生冲突,主要是为了辅助其他的在获取表锁的时候加快效率
  • 意向锁存在的意义是为了更高效的获取表锁(表格中的X和S指的是表锁,不是行锁!)
  • 意向锁是表级锁协调表锁和行锁的共存关系。主要目的是显示事务正在锁定某行或者试图锁定某行。

分析事务1获取行X锁和事务2获取表S锁:

首先事务1需要给表的第10行数据加X锁,于是InnoDB存储引擎自动给整张表加上了IX锁。当事务2再想获取整张表的S锁时,看到这张表已经有别的事务获取了IX锁了,就说明这张表肯定有某些数据被加上了X锁,这就导致事务2不能给整张表加S锁了。此时事务2只能等待,无法成功获取表S锁

三、死锁

1. 数据库中的死锁

MyISAM表锁时deadlock free的,这是因为MyISAM 不支持事务,只支持表锁,总是一次获得所需的全部锁,要么全部满足,要么等待,因此不会出现死锁。但在InnoDB中,除单个SQL组成的事务外,锁是逐步获得的,即锁的粒度比较小,这就决定了在InnoDB中发生死锁是可能的。当然如果处理多张表,还是有可能出现死锁的。

死锁问题一般都是我们自己造成的,和多线程编程的死锁情况相似,大部分都是由于我们多个线程在获取多个锁资源的时候,获取的顺序不同而导致的死锁问题。因此我们应用在对数据库的多个表做更新的时候,不同的代码段,应对这些表按相同的顺序进行更新操作,以防止锁冲突导致死锁问题。

2. 死锁场景以及解决方法

死锁出现的场景如下:

事务1成功获取行锁1
事务2成功获取行锁2

事务1无法获取行锁2,被阻塞的同时没有办法执行commit/rollback,无法释放行锁1
事务2无法获取行锁1,被阻塞的同时没有办法执行commit/rollback,无法释放行锁2

MySQL的意向共享锁、意向排它锁和死锁

所有的事务都阻塞了,相当于进程内的所有线程都阻塞了,造成了死锁问题。

解决死锁的方法:多个事务/线程获取多个相同资源锁的时候,应该按照同样的顺序,获取资源的锁。

事务被阻塞或者死锁了,mysqld(MySQL Server守护进程)设置有事务阻塞的超时时间,事务不会阻塞很长时间,超时后事务处理失败,自动释放当前占有的锁。

3. 操作

设置手动提交和可重复读隔离级别并开启事务

MySQL的意向共享锁、意向排它锁和死锁

查询一下表数据,在可重复读隔离级别使用的是MVCC提供的快照读,并没有加锁

MySQL的意向共享锁、意向排它锁和死锁

事务1获取id=7的排他锁,事务2获取id=8的排他锁

MySQL的意向共享锁、意向排它锁和死锁

事务1再获取id=8的排它锁,发生阻塞

MySQL的意向共享锁、意向排它锁和死锁

事务2再获取id=7的排它锁,发生阻塞

MySQL的意向共享锁、意向排它锁和死锁

此时由于MySQL Server检测到发生了死锁,于是解除事务1的阻塞,进行事务1的rollback,释放其占有的行锁,于是事务2成功获取id=7的排它锁

三、锁的优化建议

  • 在能正确完成业务的前提下,为确保效率,尽量使用较低的隔离级别(必须避免脏读)
  • 设计合理的索引并尽量使用索引访问数据,使加锁更准确,减少锁冲突的机会,提高并发能力
  • 选择合理的事务大小,小事务发生锁冲突的概率小(事务越大,包含的SQL越多,可能包含更多的表资源和行资源的锁,增大了锁冲突的概率)不同的程序访问一组表时,应尽量约定以相同的顺序访问各表,对一个表而言,尽可能以固定的顺序存取表中的行。这样可以大大减少死锁的机会
  • 尽量用相等条件访问数据,这样可以避免间隙锁对并发插入的影响(其实等值查询也会加间隙锁)不要申请超过实际需要的锁级别
  • 除非必须,查询时不要显示加锁(在已提交读和可重复读隔离级别,MVCC提供了读取机制,不需要手动加锁)

到此这篇关于MySQL的意向共享锁、意向排它锁和死锁的文章就介绍到这了,更多相关MySQL锁内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

MySQL 相关文章推荐
MySQL之PXC集群搭建的方法步骤
May 25 MySQL
MySQL系列之十三 MySQL的复制
Jul 02 MySQL
Mysql关于数据库是否应该使用外键约束详解说明
Oct 24 MySQL
解析MySQL索引的作用
Mar 03 MySQL
MySQL中B树索引和B+树索引的区别详解
Mar 03 MySQL
Mysql分析设计表主键为何不用uuid
Mar 31 MySQL
MySQL事务操作的四大特性以及并发事务问题
Apr 12 MySQL
Mysql 文件配置解析介绍
May 06 MySQL
详解Mysql数据库平滑扩容解决高并发和大数据量问题
May 25 MySQL
Mysql数据库事务的脏读幻读及不可重复读详解
May 30 MySQL
MySQL分布式恢复进阶
Jul 23 MySQL
MySQL性能指标TPS+QPS+IOPS压测
Aug 05 MySQL
Mysql数据库group by原理详解
delete in子查询不走索引问题分析
Jul 07 #MySQL
MySQL提升大量数据查询效率的优化神器
mysql查看表结构的三种方法总结
Jul 07 #MySQL
MySQL中正则表达式(REGEXP)使用详解
MySQL实现字段分割一行转多行的示例代码
MySQL控制流函数(-if ,elseif,else,case...when)
Jul 07 #MySQL
You might like
PHP 数组入门教程小结
2009/05/20 PHP
php抽奖概率算法(刮刮卡,大转盘)
2020/04/17 PHP
PHP用户验证和标签推荐的简单使用
2016/10/31 PHP
php 判断IP为有效IP地址的方法
2018/01/28 PHP
Thinkphp5.0框架的Db操作实例分析【连接、增删改查、链式操作等】
2019/10/11 PHP
使用Javascript和DOM Interfaces来处理HTML
2006/10/09 Javascript
struts2 jquery 打造无限层次的树
2009/10/23 Javascript
探讨在JQuery和Js中,如何让ajax执行完后再继续往下执行
2013/07/09 Javascript
用JavaScript实现动画效果的方法
2013/07/20 Javascript
js中通过split函数分割字符串成数组小例子
2013/09/21 Javascript
javascript计时器事件使用详解
2014/01/07 Javascript
NodeJS制作爬虫全过程
2014/12/22 NodeJs
jQuery中next方法用法实例
2015/04/24 Javascript
JavaScript中的Math.atan2()方法使用详解
2015/06/15 Javascript
jquery $.trim()去除字符串空格的实现方法【附图例】
2016/03/30 Javascript
AngularJS服务service用法总结
2016/12/13 Javascript
JavaScript中防止微信浏览器被整体拖动的方法
2017/08/25 Javascript
解决Vue打包之后文件路径出错的问题
2018/03/06 Javascript
微信小程序页面间传值与页面取值操作实例分析
2019/04/30 Javascript
[01:07:15]DOTA2-DPC中国联赛 正赛 DLG vs XG BO3 第二场 1月25日
2021/03/11 DOTA
[01:28]国服启动器接入蒸汽平台操作流程视频
2021/03/11 DOTA
Python简单实现TCP包发送十六进制数据的方法
2016/04/16 Python
Python3利用print输出带颜色的彩色字体示例代码
2019/04/08 Python
python 反编译exe文件为py文件的实例代码
2019/06/27 Python
python被修饰的函数消失问题解决(基于wraps函数)
2019/11/04 Python
浅谈Python 参数与变量
2020/06/20 Python
小米旗下精品生活电商平台:小米有品
2018/12/18 全球购物
一套C++笔试题面试题
2012/06/06 面试题
小学生安全保证书
2014/02/01 职场文书
进步之星获奖感言
2014/02/22 职场文书
安全宣传标语口号
2014/06/06 职场文书
公司领导班子四风对照检查材料
2014/09/27 职场文书
党员领导干部民主生活会批评与自我批评发言
2014/09/28 职场文书
行为习惯主题班会
2015/08/14 职场文书
选择比努力更重要?这是长期以来对“努力”的最大误解
2019/07/12 职场文书
OpenCV中resize函数插值算法的实现过程(五种)
2021/06/05 Python