当前位置:网站首页>Mysql 死锁和死锁的解决方案
Mysql 死锁和死锁的解决方案
2022-08-05 07:02:00 【三3三】
最近在研究Mysql底层原理,研究到了死锁,感觉挺有意思,在这里和大家分享一下
前置知识:需要了解锁的种类,如表锁、行锁;行锁又分为记录锁、间隙锁、临键锁等等;什么情况下会加表锁,什么情况下会加行锁,什么情况下会加临键锁,什么情况锁会升级等等。。。网上讲解很多,这里就不单独讲述了
一 表死锁
产生原因:
用户A访问表A(锁住了表A),然后又访问表B;另一个用户B访问表B(锁住了表B),然后企图访问表A;这时用户A由于用户B已经锁住表B,它必须等待用户B释放表B才能继续,同样用户B要等用户A释放表A才能继续,这就死锁就产生了。
用户A–>A表(表锁)–>B表(表锁)
用户B–>B表(表锁)–>A表(表锁)
解决方案:
这种死锁比较常见,是由于程序的BUG产生的,除了调整的程序的逻辑没有其它的办法。仔细分析程序的逻辑,对于数据库的多表操作时,尽量按照相同的顺序进行处理,尽量避免同时锁定两个资源,如操作A和B两张表时,总是按先A后B的顺序处理, 必须同时锁定两个资源时,要保证在任何时刻都应该按照相同的顺序来锁定资源。
二 行死锁
产生原因1:
如果在事务中执行了一条没有索引条件的查询,引发全表扫描,把行级锁上升为全表记录锁定(等价于表级锁),多个这样的事务执行后,就很容易产生死锁和阻塞,最终应用系统会越来越慢,发生阻塞或死锁。
解决方案1:
SQL语句中不要使用太复杂的关联多表的查询;使用explain“执行计划"对SQL语句进行分析,对于有全表扫描和全表锁定的SQL语句,建立相应的索引进行优化。
产生原因2:
两个事务分别想拿到对方持有的锁,互相等待,于是产生死锁。
例如:
事务A
Begin;
Select * from t1 where id = 1 for update;
Update t1 set name = ‘aa’ where id = 5;
事务B
Begin;
Delete from t1 where id = 5;
Delete from t1 where id = 1;
事务A获取到了id=1的记录锁,执行update的时候,需要拿到id=5的锁;同时事务B拿到了id=5的记录锁,又需要拿到id=1的锁,因此两个事务同时进入无线阻塞状态,这就产生了死锁。
产生原因3:
每个事务即使只有一个SQL,但是有些情况还是会发生死锁
事务A,从name索引出发 , 读到的[hdc, 1], [hdc, 6]均满足条件, 不仅会加name索引上的记录X锁, 而且会加聚簇索引上的记录X锁, 加锁顺序为先[1,hdc,100], 后[6,hdc,10]
事务B,从pubtime索引出发,[10,6],[100,1]均满足过滤条件,同样也会加聚簇索引上的记录X锁,加锁顺序为[6,hdc,10],后[1,hdc,100]。
但是加锁时发现事务B跟事务A的加锁顺序正好相反,两个事务恰好都持有了第一把锁,请求加第二把锁,死锁就发生了。
如下图所示:
解决方案2、3:
上面的原因2和原因3出现死锁的原因, 都是对索引加锁顺序的不一致导致的,所以如果可以,尽量以相同的顺序来访问索引记录和表。在程序以批量方式处理数据的时候,如果事先对数据排序,保证每个线程按固定的顺序来处理记录,也可以大大降低出现死锁的可能;
三 死锁总结
- 对索引加锁顺序的不一致很可能会导致死锁, 所以如果可以, 尽量以相同的顺序来访问索引记录和表. 在程序以批量方式处理数据的时候, 如果事先对数据排序, 保证每个线程按固定的顺序来处理记录, 也可以大大降低出现死锁的可能.
- 间隙锁往往是程序中导致死锁的真凶, 由于默认情况下 MySQL 的隔离级别是 RR,所以如果能确定幻读和不可重复读对应用的影响不大, 可以考虑将隔离级别改成 RC, 可以避免 Gap 锁导致的死锁.
- 为表添加合理的索引, 如果不走索引将会为表的每一行记录加锁, 死锁的概率就会大大增大.
- 避免大事务, 尽量将大事务拆成多个小事务来处理. 因为大事务占用资源多, 耗时长, 与其他事务冲突的概率也会变高.
- 避免在同一时间点运行多个对同一表进行读写的脚本, 特别注意加锁且操作数据量比较大的语句.
- 设置锁等待超时参数:innodb_lock_wait_timeout,在并发访问比较高的情况下,如果大量事务因无法立即获得所需的锁而挂起,会占用大量计算机资源,造成严重性能问题,甚至拖跨数据库。我们通过设置合适的锁等待超时阈值,可以避免这种情况发生。
边栏推荐
猜你喜欢

算法拾遗十五补链表相关面试题

IO进程线程->进程间的通信->day7

AI + video technology helps to ensure campus security, how to build a campus intelligent security platform?

AI+视频技术助力保障校园安全,校园智能安防平台该如何建设?

风控特征的优化分箱,看看这样教科书的操作

typescript63-索引签名类型

Put Cloudflare on the website (take Tencent Cloud as an example)

在anaconda Promat界面import torch通过,在jupyter notebook中报错的问题(仅提供思路理解!)

HR:这样的简历我只看了5秒就扔了,软件测试简历模板想要的进。

protobuf is compiled against the associated .proto file
随机推荐
配合屏幕录像专家,又小又清晰!
线程池的创建及参数设置详解
专用机终端安装软件后报IP冲突
Vulnhub靶机:HA_ NARAK
GAN generates anime avatar Pytorch
【JVM调优】Xms和Xmx为什么要保持一致
环网冗余式CAN/光纤转换器 CAN总线转光纤转换器中继集线器hub光端机
typescript63-索引签名类型
栈与队列的基本介绍和创建、销毁、出入、计算元素数量、查看元素等功能的c语言实现,以及栈的压入、弹出序列判断,栈结构的链式表示与实现
MySQL:order by排序查询,group by分组查询
re正则表达式
RNote108---显示R程序的运行进度
Illegal key size 报错问题
U++ UE4官方文档课后作业
腾讯业务安全岗 IDP 谈话总结
对数据类型而言运算符无效。运算符为 add,类型为 text。
腾讯实习总结
1, Citrix XenDesktop 2203 AD domain system installation (1)
Why does Mysql fail to create a database
【网友真实投稿】为女友放弃国企舒适圈,转行软件测试12k*13薪
