MySQL死锁使用详解及检测和避免方法 |
前言上一篇博客我们知道的Mysql事务的隔离机制和实现,以及锁的详细解析 链接: MySQL脏读幻读不可重复读及事务的隔离级别和MVCC、LBCC实现 在我们使用锁的时候,有一个问题是需要注意和避免的,我们知道,排它锁有互斥的特性 。一个事务或者说一个线程持有锁的时候,会阻止其他的线程获取锁,这个时候会造成阻塞等待,如果循环等待,会有可能造成死锁 。 这个问题我们需要从几个方面来分析,一个是锁为什么不释放,第二个是被阻塞了怎么办,第三个死锁是怎么发生的,怎么避免 。 锁的释放与阻塞
如果一个事务一直未释放锁,其他事务会被阻塞多久?会不会永远等待下去? 线上怕不怕这个错? [Err] 1205 - Lock wait timeout exceeded; try restarting transaction MySQL有一个参数来控制获取锁的等待时间,默认是50秒 。 show VARIABLES like "innodb_lock_wait_timeout"; 对于死锁,是无论等多久都不能获取到锁的,这种情况,也需要等待50秒钟吗?那不是白白浪费了50秒钟的时间吗? 死锁的发生和检测演示一下,开两个会话: 方便对时间线的提现,这里用图片,有兴趣的可以跟着模仿一下 栗子一: 栗子二: 在第一个事务中,检测到了死锁,马上退出了,第二个事务获得了锁,不需要等待50秒: [Err] 1213 - Deadlock found when trying to get lock; try restarting transaction 为什么可以直接检测到呢?是因为死锁的发生需要满足一定的条件,对于我们程序员来说,有明确的条件,意味着能判定,所以在发生死锁时,InnoDB一般都能通过算法(wait-for graph)自动检测到 。 那么死锁需要满足什么条件?死锁的产生条件,因为锁本身是互斥的:
理发店有两个总监 。一个负责剪头的Tony老师,一个负责洗头的Kelvin老师 。Tony老师不能同时给两个人剪头,这个就叫 Tony在给别人在剪头的时候,你不能让他停下来帮你剪头,这个叫 如果锁一直没有释放,就有可能造成大量阻塞或者发生死锁,造成系统吞吐量下降,这时候就要查看是哪些事务持有了锁 。 查看锁信息(日志)首先,SHow STATUS命令中,包括了一些行锁的信息: show status like 'innodb_row_lock_%';
SHOW命令是一个概要信息 。InnoDB还提供了三张表来分析事务与锁的情况: select * from information_schema.INNODB_TRX; --当前运行的所有事务﹐还有具体的语句 select* from information_schema.INNODB_LOCKS; --当前出现的锁 select * from information_schema.INNODB_LOCK_WAITS; --锁等待的对应关系 更加详细的锁信息,开启标准监控和锁监控: 额外的监控肯定会消耗额外的性能 set GLOBAL innodb_status_output=ON; set GLOBAL innodb_status_output_locks=ON; 通过分析锁日志,找出持有锁的事务之后呢? 死锁的避免
到此这篇关于MySQL死锁使用详解及检测和避免方法的文章就介绍到这了,更多相关MySQL死锁 内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持! |