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 相关文章推荐
JDBC连接的六步实例代码(与mysql连接)
May 12 MySQL
MySQL 常见的数据表设计误区汇总
Jun 07 MySQL
MySQL修炼之联结与集合浅析
Oct 05 MySQL
浅谈MySql整型索引和字符串索引失效或隐式转换问题
Nov 20 MySQL
weblogic服务建立数据源连接测试更新mysql驱动包的问题及解决方法
Jan 22 MySQL
深入讲解数据库中Decimal类型的使用以及实现方法
Feb 15 MySQL
Mysql数据库表中为什么有索引却没有提高查询速度
Feb 24 MySQL
分享几个简单MySQL优化小妙招
Mar 31 MySQL
Mysql使用全文索引(FullText index)的实例代码
Apr 03 MySQL
MySQL数据库事务的四大特性
Apr 20 MySQL
MySQL控制流函数(-if ,elseif,else,case...when)
Jul 07 MySQL
MySQL新手入门进阶语句汇总
Sep 23 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使用base64加密解密图片示例分享
2014/01/20 PHP
学习php设计模式 php实现抽象工厂模式
2015/12/07 PHP
thinkPHP模板算术运算相关函数用法分析
2016/07/12 PHP
Yii框架小部件(Widgets)用法实例详解
2020/05/15 PHP
jQuery第三课 修改元素属性及内容的代码
2010/03/14 Javascript
Jquery Autocomplete 结合asp.net使用要点
2010/10/29 Javascript
10个基于浏览器的JavaScript调试工具分享
2013/02/07 Javascript
JS创建自定义表格具体实现
2014/02/11 Javascript
关闭时刷新父窗口两种方法
2014/05/07 Javascript
JS/Jquery判断对象为空的方法
2015/06/11 Javascript
JavaScript实现带播放列表的音乐播放器实例分享
2016/03/07 Javascript
基于JQuery打造无缝滚动新闻步骤详解
2016/03/31 Javascript
针对后台列表table拖拽比较实用的jquery拖动排序
2016/10/10 Javascript
[00:37]DOTA2上海特级锦标赛 OG战队宣传片
2016/03/03 DOTA
Python中的zipfile模块使用详解
2015/06/25 Python
python实现给数组按片赋值的方法
2015/07/28 Python
Python的网络编程库Gevent的安装及使用技巧
2016/06/24 Python
python分割列表(list)的方法示例
2017/05/07 Python
Python使用matplotlib的pie函数绘制饼状图功能示例
2018/01/08 Python
Python+matplotlib绘制不同大小和颜色散点图实例
2018/01/19 Python
Python GUI布局尺寸适配方法
2018/10/11 Python
用Python读取几十万行文本数据
2018/12/24 Python
对Python 获取类的成员变量及临时变量的方法详解
2019/01/22 Python
Python 实现训练集、测试集随机划分
2020/01/08 Python
python GUI库图形界面开发之PyQt5滑块条控件QSlider详细使用方法与实例
2020/02/28 Python
python如何构建mock接口服务
2021/01/28 Python
使用css3实现的tab选项卡代码分享
2014/12/09 HTML / CSS
介绍一下SQL Server里面的索引视图
2016/07/31 面试题
金融专业毕业生推荐信
2013/11/26 职场文书
付款委托书范本
2014/04/04 职场文书
节约粮食标语
2014/06/18 职场文书
毕业生实习期转正自我鉴定
2014/09/26 职场文书
2015年销售人员工作总结
2015/04/07 职场文书
高中开学感言
2015/08/01 职场文书
早上好问候语大全
2015/11/10 职场文书
微信小程序基础教程之echart的使用
2021/06/01 Javascript