MySQL的意向共享锁、意向排它锁和死锁
作者:菜鸟~~ 发布时间:2024-01-14 18:16:02
一、InnoDB的表级锁
在绝大多数情况下应该使用行锁,因为事务和行锁往往是选择InnoDB的理由,但个别情况下也使用表级锁。
事务需要更新大部分或全部数据,表又比较大,如果使用默认的行锁,不仅这个事务执行效率低,而且可能造成其他事务长时间等待和锁冲突事务涉及多个表,比较复杂,很可能引起死锁,造成大量事务回滚
我们希望获取表锁时,执行以下命令:
在使用表锁的时候,涉及的效率问题:
要获取一张表的共享锁S或者排它锁X,首先要确定这张表没有被其它事务获取过X锁,这张表里面的数据没有被其它事务获取过行锁X锁。
假如我们这张表有一千万个数据,怎么判断这一千万个数据哪些行有X锁?
如果想获得表的S锁,就需要判断表里面哪些行有过X锁,如果有一些行有过X锁,那么就不能获取这张表的S锁或者X锁。除了挨个检查,没有更好的办法,这就导致效率低下的问题
由于需要加表锁而去挨个遍历数据,确定是否有某些数据被加了行锁,而导致的效率低下问题。我们这里学习的意向共享锁和意向排他锁就可以解决,当要获取表的X锁是,不需要再检查表中的哪些行锁被(X或者S)占用,只需要快速检查IX和IS锁即可。
二、意向共享锁和意向排它锁
意向共享锁(IS锁):事务计划给记录加行共享锁,事务在给一行记录加共享锁前,必须先取得该表的IS锁
意向排他锁(IX锁):事务计划给记录加行排他锁,事务在给一行记录加排他锁前,必须先取得该表的IX锁
在加行锁之前,由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
所有的事务都阻塞了,相当于进程内的所有线程都阻塞了,造成了死锁问题。
解决死锁的方法:多个事务/线程获取多个相同资源锁的时候,应该按照同样的顺序,获取资源的锁。
事务被阻塞或者死锁了,mysqld(MySQL Server守护进程)设置有事务阻塞的超时时间,事务不会阻塞很长时间,超时后事务处理失败,自动释放当前占有的锁。
3. 操作
设置手动提交和可重复读隔离级别并开启事务
查询一下表数据,在可重复读隔离级别使用的是MVCC提供的快照读,并没有加锁
事务1获取id=7的排他锁,事务2获取id=8的排他锁
事务1再获取id=8的排它锁,发生阻塞
事务2再获取id=7的排它锁,发生阻塞
此时由于MySQL Server检测到发生了死锁,于是解除事务1的阻塞,进行事务1的rollback,释放其占有的行锁,于是事务2成功获取id=7的排它锁
三、锁的优化建议
在能正确完成业务的前提下,为确保效率,尽量使用较低的隔离级别(必须避免脏读)
设计合理的索引并尽量使用索引访问数据,使加锁更准确,减少锁冲突的机会,提高并发能力
选择合理的事务大小,小事务发生锁冲突的概率小(事务越大,包含的SQL越多,可能包含更多的表资源和行资源的锁,增大了锁冲突的概率)不同的程序访问一组表时,应尽量约定以相同的顺序访问各表,对一个表而言,尽可能以固定的顺序存取表中的行。这样可以大大减少死锁的机会
尽量用相等条件访问数据,这样可以避免间隙锁对并发插入的影响(其实等值查询也会加间隙锁)不要申请超过实际需要的锁级别
除非必须,查询时不要显示加锁(在已提交读和可重复读隔离级别,MVCC提供了读取机制,不需要手动加锁)
来源:https://blog.csdn.net/qq_41721746/article/details/125328989
猜你喜欢
- 今天在 ajaxian 上看到一篇文章,名为 Five Ajax Anti-pattern ,觉得讲得比较有道理,现粗略翻译一下,加一些自己
- while循环:while expression: suite_to_repeatwhile 条件: 语
- 这篇文章主要介绍了python文字和unicode/ascll相互转换函数及简单加密解密实现代码,下面我们来了解一下。import reim
- 入门scipy.optimize中,curve_fit函数可调用非线性最小二乘法进行函数拟合,例如,现在有一个高斯函数想要被拟合则调用方法如
- 在multiIndex中选定指定索引的行我们在用pandas类似groupby来使用多重index时,有时想要对多个level中的某个ind
- 本文实例讲述了Python实现Sqlite将字段当做索引进行查询的方法。分享给大家供大家参考,具体如下:默认从sqlite中获取到的数据是数
- eval是Python的一个内置函数,这个函数的作用是,返回传入字符串的表达式的结果。想象一下变量赋值时,将等号右边的表达式写成字符串的格式
- 简单介绍下SecureCRTSecureCRT是一款支持SSH(SSH1和SSH2)的终端仿真程序,简单地说是Windows下登录UNIX或
- 原文:http://blog.rexsong.com/?p=746#comments加速的关键,不是降低重量,而是减少个数。如果重量在200
- Django带来了一个高级的聚合生成框架,它使得创建RSS和Atom feeds变得非常容易。什么是RSS? 什么是Atom?RSS和Ato
- DDP 数据shuffle 的设置使用DDP要给dataloader传入sampler参数(torch.utils.data.distrib
- 一、map函数作用:map主要作用是计算一个序列或者多个序列进行函数映射之后的值语法:map(function,iterable1,iter
- 本教程详细介绍在用户注册过程中如何去验证他们的email地址。工作流程上来讲,在用户注册一个新账户后会寄送一个确认信。直到用户按指示完成了邮
- 起因前端日子写完的Python入库脚本,通过直接读取配置文件的内容(包含了数据库的ip,数据库的用户名,数据库的密码),因为配置文件中的数据
- 本文实例讲述了Thinkphp 框架基础之源码获取、环境要求与目录结构。分享给大家供大家参考,具体如下:获取ThinkPHP获取ThinkP
- 1.预构建网络class Net(nn.Module): def __init__(self): su
- 转自微信公众号:机器学习社区,经作者授权转载时间序列分析是数据科学中一个非常重要的领域,它主要包含统计分析、检测变化点、异常检测和预测未来趋
- 下面是虚机维护中,经常碰到的一些ASP程序中的数据库调用的错误,现收集整理如下:
- 出差到了中国雅虎,这里的风格和淘宝很不一样。和雅虎一比,淘宝的办公环境就是个菜市场,闹哄哄,到处是人,在走道里狂奔乱窜,在每个会议室争得面红
- 今天模拟定义map函数.写着写着就发现Python可变长度参数的机制真是灵活而强大.假设有一个元组t,包含n个成员:t=(arg1,...,