JAVA全系列 教程
3762个小节阅读:7091.1k
目录
C语言快速入门
JAVA全系列 教程
面向对象的程序设计语言
Python全系列 教程
Python3.x版本,未来主流的版本
人工智能 教程
顺势而为,AI创新未来
大厂算法 教程
算法,程序员自我提升必经之路
C++ 教程
一门通用计算机编程语言
微服务 教程
目前业界流行的框架组合
web前端全系列 教程
通向WEB技术世界的钥匙
大数据全系列 教程
站在云端操控万千数据
AIGC全能工具班
A A
White Night
死锁是并发系统中常见的问题,同样也会出现在数据库MySQL的并发读写请求场景中。当两个及以上的事务,双方都在等待对方释放已经持有的锁或因为加锁顺序不一致造成循环等待锁资源,就会出现“死锁”。
xxxxxxxxxx
Deadlock found when trying to get lock...
举例来说 A 事务持有 X1 锁 ,申请 X2 锁,B事务持有 X2 锁,申请 X1 锁。A 和 B 事务持有锁并且申请对方持有的锁进入循环等待,就造成了死锁。
出现死锁的几个要素:
- 两个或者两个以上事务
- 每个事务都已经持有锁并且申请新的锁
- 锁资源同时只能被同一个事务持有或者不兼容
- 事务之间因为持有锁和申请锁导致彼此循环等待
打开终端A,登录MySQL,将事务隔离级别设置为可重复读,开启事务后为userinfo数据表中id为1的数据添加排他锁,如下所示。
xxxxxxxxxx
mysql> set session transaction isolation level repeatable read;
Query OK, 0 rows affected (0.00 sec)
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from userinfo;
+----+-------+---------+
| id | name | balance |
+----+-------+---------+
| 1 | Java | 100.00 |
| 2 | MySQL | 200.00 |
+----+-------+---------+
2 rows in set (0.00 sec)
打开终端B,登录MySQL,将事务隔离级别设置为可重复读,开启事务后为userfinfo数据表中id为2的数据添加排他锁,如下所示。
xxxxxxxxxx
mysql> set session transaction isolation level repeatable read;
Query OK, 0 rows affected (0.00 sec)
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from userinfo where id = 2;
+----+-------+---------+
| id | name | balance |
+----+-------+---------+
| 2 | MySQL | 200.00 |
+----+-------+---------+
1 row in set (0.00 sec)
在终端A为userinfo数据表中id为2的数据添加排他锁,如下所示。
xxxxxxxxxx
mysql> select * from userinfo where id =2 for update;
注意:
此时,线程会一直卡住,因为在等待终端B中id为2的数据释放排他锁。
在终端B中为userinfo数据表中id为1的数据添加排他锁,如下所示。
xxxxxxxxxx
mysql> select * from userinfo where id =1 for update;
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction
通过如下命令可以查看死锁的日志信息。
xxxxxxxxxx
show engine innodb status\G
注意:
通过命令行查看LATEST DETECTED DEADLOCK选项相关的信息,可以发现死锁的相关信息,或者通过配置innodb_print_all_deadlocks(MySQL 5.6.2版本开始提供)参数为ON,将死锁相关信息打印到MySQL错误日志中。
1、合理的设计索引,区分度高的列放到组合索引前面,使业务 SQL 尽可能通过索引定位更少的行,减少锁竞争
。
2、调整业务逻辑 SQL 执行顺序, 避免 update/delete 长时间持有锁的 SQL 在事务前面。
3、合理设计索引,尽量缩小锁的范围。
4、尽量减少查询条件的范围,尽量避免间隙锁或缩小间隙锁的范围。
5、尽量控制事务的大小,减少一次事务锁定的资源数量,缩短锁定资源的时间。
6、如果一条SQL语句涉及事务加锁操作,则尽量将其放在整个事务的最后执行。
7、优化 SQL 和表设计,减少同时占用太多资源的情况。比如说,减少连接的表
,将复杂 SQL 分解
为多个简单的 SQL。
实时效果反馈
1.如何避免死锁下列描述正确的是_____。
A 合理设计索引,尽量缩小锁的范围。
B 尽量缩小锁的范围尽量避免间隙锁或缩小间隙锁的范围。
C 避免大事务,尽量将大事务拆成多个小事务来处理
D 以上都正确
答案
1=>D