MySQL遇到一死锁现象,记录一下

本文详细阐述了在使用最高隔离级别(SERIALIZABLE)时,事务间出现死锁的现象及其原因。通过具体示例展示了在尝试执行 select、insert 和 update 操作时,两个并发事务之间的死锁情况。文章进一步探讨了解决此类问题的两种方法:改变事务隔离级别以允许并发操作,或调整查询顺序以避免冲突。同时强调了在实际应用中合理选择事务隔离级别的重要性。
遇到一死锁现象:
事务级别中使用了最高的隔离级别:
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE

一个事件中,先select,如果没有则insert,有则update
当两个请求同事到达时,死锁发生了

下面详细描述一下:

CREATE TABLE `t1` (
  `a` int(11) NOT NULL,
  `b` int(11) DEFAULT NULL,
  PRIMARY KEY (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;



事务1                                            事务2


begin;
select * from t1 where a = 88; #select会自动加一把共享锁
Empty set (0.00 sec)


                                                 begin;
                                                 select * from t1 where a = 88; #几乎同一时间也加了一把共享锁
                                                 Empty set (0.00 sec)
                                                 insert into t1 values(88, 10000);  #由于事务1加了共享锁,插入要等事务1提交
                                                 
insert into t1 values(88, 10000);
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction
#因为发现没有记录存在,也执行插入
#但是由于事务2也加了一把共享锁,导致死锁
#当前事务被迫结束并rollback了




                                                 Query OK, 1 row affected (6.37 sec) #插入成功

                                                                                                  

这种情况就是由于事务的隔离级别为SERIALIZABLE,select语句会隐式地加上LOCK IN SHARE MODE,但是这并不影响select查询出结果,它只是不可以修改

本想在select语句上显示地加上FOR UPDATE互斥锁,强制让另一事件查询都阻塞,但是因为那条记录一开始就不存在,FOR UPDATE并不能起作用,两个事务仍然都可以select,并且均返回无记录


那如何解决这个问题呢? 有两种方法:


一种是事件隔离级别设置为非SERIALIZABLE,select这里都会成功,应用层两个事件中都会继续执行,这样子一个事务插入成功了

但是另一事务肯定会插入失败,但是由于上面select语句均返回无记录,但确在插入时出错了,调用失败了,调用端发现失败只能重新发送请求 

另一种方法是,先不要select,先执行insert,然后根据结是否重复决定事务的后面处理流程,这样子一个事务插入成功,另一事务肯定会插入重复,重复后再执行修改


具体要根据业务特点决定使用适合的解决方法。


另外:大多数情况下不需要用到"SERIERLIZED"这个隔离级别,一般情况下"READ-COMMITTED"就可以满足要求了。

       
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值