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 Router的安装部署
Apr 24 MySQL
MySQL不使用order by实现排名的三种思路总结
Jun 02 MySQL
zabbix监控mysql的实例方法
Jun 02 MySQL
解析MySQL binlog
Jun 11 MySQL
MySQL into_Mysql中replace与replace into用法案例详解
Sep 14 MySQL
mysql中int(3)和int(10)的数值范围是否相同
Oct 16 MySQL
mysql下的max_allowed_packet参数设置详解
Feb 12 MySQL
解决MySQL报“too many connections“错误
Apr 19 MySQL
mysql 索引的数据结构为什么要采用B+树
Apr 26 MySQL
深入理解MySQL中MVCC与BufferPool缓存机制
May 25 MySQL
MySQL详解进行JDBC编程与增删改查方法
Jun 16 MySQL
MySQL 原理优化之Group By的优化技巧
Aug 14 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
我的论坛源代码(六)
2006/10/09 PHP
php 判断访客是否为搜索引擎蜘蛛的函数代码
2011/07/29 PHP
解析php开发中的中文编码问题
2013/08/08 PHP
php检测网页是否被百度收录的函数代码
2013/10/09 PHP
php根据一个给定范围和步进生成数组的方法
2015/06/19 PHP
纯php生成随机密码
2015/10/30 PHP
windows平台中配置nginx+php环境
2015/12/06 PHP
jQuery 获取URL的GET参数值的小例子
2013/04/18 Javascript
Jquery判断$("#id")获取的对象是否存在的方法
2013/09/25 Javascript
JS中三目运算符和if else的区别分析与示例
2014/11/21 Javascript
jQuery知识点整理
2015/01/30 Javascript
JQuery中模拟image的ajaxPrefilter与ajaxTransport处理
2015/06/19 Javascript
JavaScript函数中关于valueOf和toString的理解
2016/06/14 Javascript
Web性能优化系列 10个提升JavaScript性能的技巧
2016/09/27 Javascript
JavaScript易错知识点整理
2016/12/05 Javascript
谈谈jQuery之Deferred源码剖析
2016/12/19 Javascript
详解Vue.js组件可复用性的混合(mixin)方式和自定义指令
2017/09/06 Javascript
详解vue-element Tree树形控件填坑路
2019/03/26 Javascript
详解vue-cli3开发Chrome插件实践
2019/05/29 Javascript
vue中的过滤器实例代码详解
2019/06/06 Javascript
JS实现灯泡开关特效
2020/03/30 Javascript
关于Vue中$refs的探索浅析
2020/11/05 Javascript
python实现爬虫统计学校BBS男女比例(一)
2015/12/31 Python
Python获取当前公网ip并自动断开宽带连接实例代码
2018/01/12 Python
Python中elasticsearch插入和更新数据的实现方法
2018/04/01 Python
python3+PyQt5 实现Rich文本的行编辑方法
2019/06/17 Python
使用浏览器访问python写的服务器程序
2019/10/10 Python
如何使用Python处理HDF格式数据及可视化问题
2020/06/24 Python
python中如何写类
2020/06/29 Python
python如何控制进程或者线程的个数
2020/10/16 Python
python tkinter实现连连看游戏
2020/11/16 Python
css3绘制百度的小度熊
2018/10/29 HTML / CSS
电脑销售顾问自荐信
2014/01/29 职场文书
总会计师岗位职责
2014/02/19 职场文书
不服从上级领导安排的检讨书
2014/09/14 职场文书
银行授权委托书范本
2014/10/04 职场文书