mysql 死锁和锁等待

149 阅读2分钟
事务1事务2现象
Begin;Begin;
update t_user set name="11" where id=1;update t_user set name="22" where id=2;
update t_user set name="111" where id=2;锁等待
update t_user set name="222" where id=1;死锁

1. 锁等待

1.1 锁等待定义

当事务1请求事务2所持有记录,而该记录又被事务2上排他锁,这个时候事务1 就需要等待该锁的释放,这种现象就叫锁等待。

1.2 锁等待的解决方法

?待完成... 参考:www.51cto.com/article/615…

1.2.1 解决

2. 死锁

2.1 死锁定义

并发下的线程,互相等待对方所持有的资源,导致无限阻塞的现象称之为死锁。 如上图所示,当事务1和事务2 同时请求对对方所持有资源加排他锁时,就会发生死锁。
【持有资源:表示当前事务已对该资源加了排他锁。】

2.2 死锁的四大原因

2.2.1 互斥

线程所持有的资源具有互斥性,即只能被一个线程持有。

2.2.2 占有且等待

两个线程都占有着资源,且同时等待对方的资源释放。

2.2.3 无法抢占

资源一旦被一个线程持有了,就无法被其他线程抢占,必须等当前线程释放资源。

2.2.4 循环等待

两个线程都在等待对方释放资源,一直不停的阻塞等待。

2.3 死锁的定位方法

2.3.1 可以通过下面的sql语句,查看死锁的详细信息

show engine innodb status;

2.3.2 查询结果:

image.png

2.3.3 copy 出来到文本编辑器,搜索 deadlock:

image.png

2.4 死锁如何避免

1. 互斥性是锁的基本特性。一般无法处理。

2. 占有且等待:可以给当前线程设置过期时间,防止死锁

3. 无法抢占:可以让线程刚开始执行,就锁定所需的全部资源。

4. 循环等待:让两个线程以相同的顺序锁定相关资源,串行化执行。


5. 针对mysql 的死锁:

5.1 大事务拆成小事务,减少事务的锁定资源,缩短锁定时间

5.2 尽量缩小锁的范围,例如表锁尽量压缩成间隙锁,间隙锁压缩成行锁

5.3 尽量使用索引,避免表锁。

5.4 合理设计索引,缩小锁定范围

5.5 使用低级别的事务隔离级别 :RR -> RC

5.6 尽量将加锁的操作放到事务的最后去执行