MySQL相关 – 死锁的发生和避免

MySQL相关 – 死锁的发生和避免

大家好,又见面了,我是全栈君。

在我们使用锁的时候,有一个问题是需要注意和避免的,我们知道,排它锁有互斥的特性。一个事务或者说一个线程持有锁的时候,会阻止其他的线程获取锁,这个时候会造成阻塞等待,如果循环等待,会有可能造成死锁

这个问题我们需要从几个方面来分析,一个是锁为什么不释放,第二个是被阻塞了怎么办,第三个死锁是怎么发生的,怎么避免。我们且看正文部分。

: 在这里插入图片描述

正文

死锁

锁的释放与阻塞

回顾:锁什么时候释放?

事务结束(commit,rollback);客户端连接断开。

如果一个事务一直未释放锁,其他事务会被阻塞多久?会不会永远等待下去?如果是,在并发访问比较高的情况下,如果大量事务因无法立即获得所需的锁而挂起,会占用大量计算机资源,造成严重性能问题,甚至拖跨数据库。

[Err] 1205 – Lock wait timeout exceeded; try restarting transaction MySQL 有一个参数来控制获取锁的等待时间,默认是 50 秒。

show VARIABLES like 'innodb_lock_wait_timeout';

在这里插入图片描述

对于死锁,是无论等多久都不能获取到锁的,这种情况,也需要等待 50 秒钟吗?那

不是白白浪费了 50 秒钟的时间吗?

我们先来看一下什么时候会发生死锁。

死锁的发生和检测

死锁演示:

Session 1 Session 2
begin;<br/>select * from t2 where id =1 for update;  
begin;<br />delete from t2 where id =4 ;
update t2 set name= ‘4d’ where id =4 ;  
delete from t2 where id =1 ;

在第一个事务中,检测到了死锁,马上退出了,第二个事务获得了锁,不需要等待 50 秒:

[Err] 1213 – Deadlock found when trying to get lock; try restarting transaction

为什么可以直接检测到呢?是因为死锁的发生需要满足一定的条件,所以在发生死锁时,InnoDB 一般都能通过算法(wait-for graph)自动检测到。

那么死锁需要满足什么条件?死锁的产生条件:

因为锁本身是互斥的 (1)同一时刻只能有一个事务持有这把锁; (2)其他的事务需要在这个事务释放锁之后才能获取锁,而不可以强行剥夺; (3)当多个事务形成等待环路的时候,即发生死锁。

举例:

理发店有两个总监。一个负责剪头的 Tony 总监,一个负责洗头的 Kelvin 总监。

Tony 不能同时给两个人剪头,这个就叫互斥。

Tony 在给别人在剪头的时候,你不能让他停下来帮你剪头,这个叫不能强行剥夺。如果 Tony 的客户对 Kelvin 总监说:你不帮我洗头我怎么剪头?Kelvin 的客户对 Tony 总监说:你不帮我剪头我怎么洗头?这个就叫形成等待环路。

如果锁一直没有释放,就有可能造成大量阻塞或者发生死锁,造成系统吞吐量下降,这时候就要查看是哪些事务持有了锁。

查看锁信息(日志)

SHOW STATUS 命令中,包括了一些行锁的信息:

show status like 'innodb_row_lock_%';

在这里插入图片描述

  • Innodb_row_lock_current_waits:当前正在等待锁定的数量;
  • Innodb_row_lock_time :从系统启动到现在锁定的总时间长度,单位 ms;
  • Innodb_row_lock_time_avg :每次等待所花平均时间;
  • Innodb_row_lock_time_max:从系统启动到现在等待最长的一次所花的时间;
  • Innodb_row_lock_waits :从系统启动到现在总共等待的次数。

SHOW 命令是一个概要信息。InnoDB 还提供了三张表来分析事务与锁的情况:

select * from information_schema.INNODB_TRX;	-- 当前运行的所有事务 ,还有具体的语句

在这里插入图片描述

select * from information_schema.INNODB_LOCKS;	--  当前出现的锁

在这里插入图片描述

select * from information_schema.INNODB_LOCK_WAITS;	--  锁等待的对应关系

在这里插入图片描述

找出持有锁的事务之后呢?

如果一个事务长时间持有锁不释放,可以 kill 事务对应的线程 ID ,也就是 INNODB_TRX 表中的 trx_mysql_thread_id,例如执行 kill 4,kill 7,kill 8。

当然,死锁的问题不能每次都靠 kill 线程来解决,这是治标不治本的行为。我们应该尽量在应用端,也就是在编码的过程中避免。

有哪些可以避免死锁的方法呢?

死锁的避免

  1. 在程序中,操作多张表时,尽量以相同的顺序来访问(避免形成等待环路);
  2. 批量操作单张表数据的时候,先对数据进行排序(避免形成等待环路);
  3. 申请足够级别的锁,如果要操作数据,就申请排它锁;
  4. 尽量使用索引访问数据,避免没有 where 条件的操作,避免锁表;
  5. 如果可以,大事务化成小事务;
  6. 使用等值查询而不是范围查询查询数据,命中记录,避免间隙锁对并发的影响。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/111631.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 渗透测试工具包 | 开源安全测试工具 | 网络安全工具

    渗透测试工具包 | 开源安全测试工具 | 网络安全工具项目介绍记录渗透测试开源工具。自动化渗透测试 AttackSurfaceMapper-自动化渗透测试工具,使用手册/测试流程。 vajra-自动化渗透测试. Savior-渗透测试报告自动生成工具!. 漏洞利用框架 hackUtils-它是一个用于渗透测试和网络安全研究的黑客工具包,渗透以及web攻击脚本。 msf框架: pocsscan攻击框架 Pocsuite攻击框架 Beebeeto攻击框架 …

    2022年8月12日
    6
  • java nio 如何使用_Java NIO 系列教程[通俗易懂]

    java nio 如何使用_Java NIO 系列教程[通俗易懂]JavaNIO(NewIO)是从Java1.4版本开始引入的一个新的IOAPI,可以替代标准的JavaIOAPI。本系列教程将有助于你学习和理解JavaNIO。JavaNIO提供了与标准IO不同的IO工作方式:ChannelsandBuffers(通道和缓冲区):标准的IO基于字节流和字符流进行操作的,而NIO是基于通道(Channel)和缓冲区(Buffer)进行操作,数据总…

    2022年7月8日
    22
  • Oracle新建索引、删除索引和查看索引

    Oracle新建索引、删除索引和查看索引1、创建索引createindex索引名on表名(列名);2、删除索引dropindex索引名;3、创建组合索引createindex索引名on表名(列名1,列名2,列名3,…);查看目标表中已添加的索引–在数据库中查找表名select*fromuser_tableswheretable_namelike‘tablename%’;–查看该表的所有索引select*fromall_indexeswheretable_name=‘tablen

    2022年9月4日
    3
  • python分类模型_nlp模型评估指标

    python分类模型_nlp模型评估指标不知道你是否已经看完了我之前讲过的有关机器学习的文章,如果没看过也没关系,因为本篇文章介绍的内容适用于所有分类模型(包括神经网络),主要就是介绍分类模型的评估指标。另外,在前面我还会提一下数据不平衡的问题该如何处理。总之本篇文章实用性极强!…

    2022年10月6日
    0
  • string.h 或 cstring 头文件包含的字符串操纵函数查询「建议收藏」

    string.h 或 cstring 头文件包含的字符串操纵函数查询「建议收藏」参考网站:http://www.cplusplus.com/reference/cstring/头文件函数问题尽量去官网,或权威网站查找信息,知识全面

    2022年9月12日
    0
  • 像素,分辨率,PPI(像素密度),BPP 扫盲

    像素,分辨率,PPI(像素密度),BPP 扫盲像素于分辨率像素,又称画素,为图像显示的基本单位,译自英文“pixel”,pix是英语单词picture的常用简写,加上英语单词“元素”element,就得到pixel,故“像素”表示“图像元素”之意,有时亦被称为pel(picture element)。每个这样的信息元素不是一个点或者一个方块,而是一个抽象的采样。仔细处理的话,一幅图像中的像素可以在任何尺度上看起来都不像分离的点或者方块;但…

    2022年5月11日
    42

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号