做公司网站的服务费入什么费用wordpress超简洁主题
死锁的产生条件
互斥、请求和保持、不可剥夺、循环等待
MySQL锁类型

死锁复现
环境:Mysql 5.7版本,Innodb引擎,可重复度隔离级别
 并发场景下使用duplicate key update插入或更新数据可能会造成死锁,下面就产生死锁的条件进行模拟
 表:
CREATE TABLE `song_rank` (`id` int(11) NOT NULL AUTO_INCREMENT,`songId` int(11) NOT NULL,`weight` int(11) NOT NULL DEFAULT '0',PRIMARY KEY (`id`),UNIQUE KEY `songId_idx` (`songId`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8
 
隔离级别:可重复度(RR)
select @@tx_isolation;
 

预先插入两条数据
| id | songId | weight | 
|---|---|---|
| 1 | 10 | 30 | 
| 2 | 20 | 30 | 

 关闭事务自动提交:
select @@autocommit;
set autocommit=0;
 

死锁场景一:
记录锁循环等待:如果两个事务并发读写相同行,会由于加锁时机的不同而造成死锁,导致其中一个事务执行失败(mysql可以配置自动检测死锁然后自动断开其中一个innodb_deadlock_detect)
## 事务一
# 第一步执行
begin;
insert into  song_rank(songId,weight) values(17,100) on duplicate key update  weight=weight+1;
# 第三步执行
insert into  song_rank(songId,weight) values(16,100) on duplicate key update  weight=weight+1;## 事务二
# 第二步执行
begin;
insert into  song_rank(songId,weight) values(16,100) on duplicate key update  weight=weight+1;
# 第四步执行
insert into  song_rank(songId,weight) values(17,100) on duplicate key update  weight=weight+1;
 
| 执行步骤 | 事务一 | 事务二 | 锁状态 | 
|---|---|---|---|
| 第一步 | begin; insert into song_rank(songId,weight) values(17,100) on duplicate key update weight=weight+1; | 事务一对17新增记录锁 | |
| 第二步 | begin;insert into song_rank(songId,weight) values(16,100) on duplicate key update weight=weight+1; | 事务二对16新增记录锁 | |
| 第三步 | insert into song_rank(songId,weight) values(16,100) on duplicate key update weight=weight+1; | 事务一等待事务二释放16的记录锁 | |
| 第四步 | insert into song_rank(songId,weight) values(17,100) on duplicate key update weight=weight+1; | 事务二等待事务一释放17的记录锁,出现死锁 | 
死锁场景二:
记录锁、间隙锁循环等待:在并发插入、更新同一条数据时,一个事务获取了记录锁,一个事务在等待记录排他锁,则事务在执行插入获取间隙锁是会造成死锁。
# 事务一
# 第一步执行
begin;
insert into  song_rank(songId,weight) values(17,100) on duplicate key update  weight=weight+1;
# 第四步执行
rollback;# 事务二
# 第二步执行
begin;
insert into  song_rank(songId,weight) values(17,100) on duplicate key update  weight=weight+1;# 事务三
# 第三步执行
begin;
insert into  song_rank(songId,weight) values(17,100) on duplicate key update  weight=weight+1;
# 出现死锁 
| 执行步骤 | 事务一 | 事务二 | 事务三 | 锁状态 | 
|---|---|---|---|---|
| 第一步 | begin; insert into song_rank(songId,weight) values(17,100) on duplicate key update weight=weight+1; | 事务一对17新增记录锁 | ||
| 第二步 | begin;insert into song_rank(songId,weight) values(17,100) on duplicate key update weight=weight+1; | 事务二等待17记录锁 | ||
| 第三步 | begin;insert into song_rank(songId,weight) values(17,100) on duplicate key update weight=weight+1; | 事务三等待17的记录锁 | ||
| 第四步 | rollback; | 事务二获取17记录锁,事务三等待17记录锁,事务一获取间隙锁时需要等待事务三释放17记录锁,出现死锁 | 
避免死锁
控制并发写入和更新;
 先执行插入,捕获插入异常并处理更新数据;
