MySQL死锁怎么检测和避免

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

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

锁的释放与阻塞

回顾:锁什么时候释放?
事务结束(commit,rollback)﹔
客户端连接断开。

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

线上怕不怕这个错?

[Err] 1205 - Lock wait timeout exceeded; try restarting transaction

MySQL有一个参数来控制获取锁的等待时间,默认是50秒。

show VARIABLES like "innodb_lock_wait_timeout";

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

死锁的发生和检测

演示一下,开两个会话:

方便对时间线的提现,这里用图片,有兴趣的可以跟着模仿一下

栗子一:

MySQL死锁怎么检测和避免

栗子二:

MySQL死锁怎么检测和避免

在名列前茅个事务中,检测到了死锁,马上退出了,第二个事务获得了锁,不需要等待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说:你不帮我剪头我怎么洗头?这个就叫形成等待环路
实际上,发生死锁的情况非常多,但是都满足以上3个条件。
这个也是表锁是不会发生死锁的原因,因为表锁的资源都是一次性获取的

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

查看锁信息(日志)

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

show status like 'innodb_row_lock_%';

MySQL死锁怎么检测和避免

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

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

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

MySQL死锁怎么检测和避免

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

MySQL死锁怎么检测和避免

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

MySQL死锁怎么检测和避免

更加详细的锁信息,开启标准监控和锁监控:

额外的监控肯定会消耗额外的性能

set GLOBAL innodb_status_output=ON;set GLOBAL innodb_status_output_locks=ON;

通过分析锁日志,找出持有锁的事务之后呢?
如果一个事务长时间持有锁不释放,可以kill事务对应的线程ID,也就是INNODB_TRX表中的trx_mysql_thread_id,例如执行kill 4,kill 7, kill 8。
当然,死锁的问题不能每次都靠kill线程来解决,这是治标不治本的行为。我们应该尽量在应用端,也就是在编码的过程中避免。
有哪些可以避免死锁的方法呢?

死锁的避免

  • 1、在程序中,操作多张表时,尽量以相同的顺序来访问(避免形成等待环路)

  • 2、批量操作单张表数据的时候,先对数据进行排序(避免形成等待环路);

  • 3、申请足够级别的锁,如果要操作数据,就申请排它锁;

  • 4、尽量使用索引访问数据,避免没有where条件的操作,避免锁表;

  • 5、如果可以,大事务化成小事务;

  • 6、使用等值查询而不是范围查询查询数据,命中记录,避免间隙锁对并发的影响。

感谢各位的阅读,以上就是“MySQL死锁怎么检测和避免”的内容了,经过本文的学习后,相信大家对MySQL死锁怎么检测和避免这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!

文章标题:MySQL死锁怎么检测和避免,发布者:亿速云,转载请注明出处:https://worktile.com/kb/p/24200

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
亿速云的头像亿速云认证作者
上一篇 2022年9月10日 下午11:42
下一篇 2022年9月10日 下午11:43

相关推荐

  • java IP归属地功能如何实现

    名列前茅步:如何拿到用户的真实IP 大家都知道,我们一般想访问公网,一般必须具备上网环境,那么我们开通宽带之后,运营商会给我们分配一个IP地址。一般IP地址我们都是自动分配的。所以我们不知道本机地址是什么?想知道自己的ip公网地址,可以通过百度搜索IP查看自己的ip位置 那么问题来了。百度是怎么知道…

    2022年9月6日
    63200
  • 电脑蓝屏0x00000050如何解决

    解决方法: 方法一: 1、应用程序冲突是较好解决的。 2、首先我们重启电脑,然后在开机时按下键盘“F8”,再选择“疑难解答” 3、接着进入高级选项,在其中找到“启动设置” 4、再按下键盘“F4”,尝试进入安全模式。如果可以进入安全模式应该就是应用程序冲突问题。 5、进入安全模式后,只需要在其中将最近…

    2022年9月18日
    68000
  • css中设置长度的单位是什么

    css长度单位有:1、em,相对字体长度单位,它的单位长度是根据元素的文本文字垂直长度来决定的;2、rem,相对字体长度单位,只相对根元素即html元素字体大小来确定其长度;3、%,相对于父元素宽度或字体大小的百分比;4、px,像素,是相对于显示器屏幕分辨率而言的;5、vw,相对于浏览器窗口的宽度;…

    2022年9月22日
    52100
  • Codeql如何分析cookie未启用httponly的问题

    序 今天我们利用codeql分析下“cookie未启用httponly“这类的安全问题,由此加深自己对codeql的使用。如果反应好的话,可以考虑把Vulnerability-goapp的其他漏洞也弄一弄。 分析go程序时必须额外下载codeql-go 说明 审计对象 Vulnerability-g…

    2022年9月15日
    46300
  • windows驱动精灵dx如何修复

    驱动精灵dx修复方法: 1、打开驱动精灵点击“百宝箱”。 2、点击右下方的“软件管理”。 3、在搜索栏中输入“Directx”。 4、找到“Directx 修复工具”点击“安装”即可。 感谢各位的阅读,以上就是“windows驱动精灵dx如何修复”的内容了,经过本文的学习后,相信大家对windows…

    2022年9月10日
    54000
  • word怎么添加页码

    word加页码的方法: 1、说先进入word文档,然后点击菜单中的“插入”选项。 2、然后在下拉的菜单中选择”页码“选项。 3、然后就会出现页码的设置框,可以点击“格式”来进行编辑。 4、然后你就可以在数字格式的模式进行格式选择,然后点击确定。 5、当你全部设置完成之后可以直接点击确定来完成设置。 …

    2022年9月20日
    46200
  • ai如何转曲文件

    ai转曲文件的方法: 1、首先双击桌面的ai软件,然后打开。 2、之后去点击任务选项栏中的“选择”。 3、点击弹出菜单中的“全部”。 4、之后点击任务选项中的“文字”。 5、点击文字下面的“创建轮廓”即可。 以上就是“ai如何转曲文件”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很…

    2022年9月1日
    1.7K00
  • windows驱动精灵amd安装失败如何解决

    驱动精灵amd安装失败: 1、安装驱动之前应该先查看一下操作系统是否合适。 32位驱动无法安装在64位驱动上。 2、安装前先检测驱动是否余有残留,将其清理干净,不然容易导致失败。 3、装之前可以先进行检测一下,如果缺少安装驱动的组件可以及时安装。 4、安装驱动前可以先将杀毒软件关闭,避免造成阻挠。 …

    2022年9月10日
    43300
  • Oracle中for循环如何使用

    Oracle for in loop 循环的一些实例,以作学习和加强使用熟练度及场景应用. 一些技巧 for 语句后面的 loop end loop 可以类比成 c#/java 等编程语言 for 语句后面的语句块符号(花括号{}), 以便理解和使用. 一些实例 循环输出数值 — 循环输出数值be…

    2022年8月29日
    54500
  • 数据库mdf文件能恢复吗

    数据库mdf文件可以恢复吗: 答:是可以恢复的。 方法一、 1、把mdf文件和ldf文件拷贝到数据库的默知认路径道C:Program FilesMicrosoft SQL ServerMSSQL10.MSSQLSERVERMSSQLDATA里。 2、在sqlserver里新建个查询,执行下面代码。 …

    2022年9月8日
    58700
站长微信
站长微信
电话联系

400-800-1024

工作日9:30-21:00在线

分享本页
返回顶部