解决最近遇到的高并发下,mysql innodb引擎的死锁问题
来源:互联网 发布:html5编程工具 编辑:程序博客网 时间:2024/05/17 07:51
最近在查生产环境上的日志,找某个问题的时候,无意中瞟见了日志中的一个异常信息:
16:17:39.420 [http-58080-207] DEBUG o.a.f.w.h.AppSimpleMappingExceptionResolver:132 - Resolving exception from handler [public org.anrhd.framework.domain.AppMap org.anrhd.framework.web.remote.DomainController.doAction(java.lang.String,java.lang.String,org.anrhd.framework.domain.AppMap,javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) throws java.io.IOException]: java.lang.RuntimeException: java.lang.RuntimeException: org.springframework.dao.DeadlockLoserDataAccessException: SqlMapClient operation; SQL []; --- The error occurred in org/anrhd/framework/dao/ibatis/criteria_SqlMap.xml. --- The error occurred while applying a parameter map. --- Check the user_acct_tran.insert-InlineParameterMap. --- Check the statement (update failed). --- Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction; nested exception is com.ibatis.common.jdbc.exception.NestedSQLException: --- The error occurred in org/anrhd/framework/dao/ibatis/criteria_SqlMap.xml. --- The error occurred while applying a parameter map. --- Check the user_acct_tran.insert-InlineParameterMap. --- Check the statement (update failed). --- Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction
,于是将这个问题记下,直到解决了刚说的前一个问题之后才腾出功夫看看这个异常信息。
从日志上来看,是innoDB出现了死锁的情况。
由于我真的没什么mysql经验,于是度娘了一番,又翻墙谷哥了一下,找到一些相关资料。
我猜测此问题是由于innoDB的行锁导致的,但是又和我所查到的博客上介绍的案例不太一致:博客上的案例给的例子是
CREATE TABLE `user_item` ( `id` BIGINT(20) NOT NULL, `user_id` BIGINT(20) NOT NULL, `item_id` BIGINT(20) NOT NULL, `status` TINYINT(4) NOT NULL, PRIMARY KEY (`id`), KEY `idx_1` (`user_id`,`item_id`,`status`) ) ENGINE=INNODB DEFAULT CHARSET=utf-8 update user_item set status=1 where user_id=? and item_id=? update user_item.....where id=?and user_id=?update user_item set status=1 where user_id=? and item_id=?
此三个update语句用三个窗口不同session同时执行,于是,死锁问题就产生了。产生的原因,作者剖析是,当执行第一个update时,innodb先给user_id索引加了行锁,然后给item_id的索引加了行锁;第二个update时,给id的索引加了行锁,再给user_id索引加行锁;第三个又和第一个一致,此时,第一个与第二个就互相等待对方的锁释放了,死锁便发生了。
而我碰到的问题则比较奇怪,因为据我非常仔细的分析日志(非常大,4个G),只发现了两条update语句(线程很多,执行次数也很多,但都是重复sql),唯一这两条sql一路排查下来,引起了我的怀疑。
update user_acct_tran set status =?,balance=?,amount=? where a_t_id=? and status='03' update user_acct_tran set status =? ,balance=?,amount=? where busines=? and status='03'
a_t_id为主键,此表没有建立任何索引,所以只有主键索引。
但是,正是这两条Sql引起了死锁!我是采取的猜测加排除法来锁定目标的,我将第二条sql的实现改为了先根据busines查找a_t_id,再根据a_t_id来进行更新,像第一条一样,
这时候,奇迹发生了,同时300个线程进行压力测试的情况下,竟然不再报死锁的异常了。之前,10个线程就报了一例!
我这个场景和前一位仁兄所遇到的并不太一致,毕竟我这里没有其它的索引,所以,到目前为止,我也没搞明白为什么会如此。但是,能解决这个棘手的问题,并且知道mysql有这样一类坑以后可以避免,我仍然感觉非常愉快~!
0 0
- 解决最近遇到的高并发下,mysql innodb引擎的死锁问题
- mysql的innodb死锁问题
- 巧用MySQL InnoDB引擎锁机制解决死锁问题
- 巧用MySQL InnoDB引擎锁机制解决死锁问题
- 最近遇到的并发问题
- MySQL InnoDB存储引擎下的锁
- mysql中innodb引擎的锁问题
- mysql死锁问题的解决
- Mysql Innodb死锁解决
- MySQL InnoDB下的死锁和锁等待超时的问题验证与梳理
- 【开卷有益】记录一次高并发下的死锁解决思考过程
- Mysql 并发引起的死锁问题
- MySQL并发引起的死锁问题
- 总结线上遇到的MySQL死锁问题
- MYSQL INNODB中GAP LOCK引起死锁的问题
- 高并发测试下的一些问题及解决
- 高并发测试下的一些问题及解决
- 高并发测试下的一些问题及解决
- maven如何修改本地仓库与中央仓库
- 【算法】哈希表
- SOCKET
- 敌兵布阵
- 深浅拷贝:即Deep Copy和Shallow Copy的区别
- 解决最近遇到的高并发下,mysql innodb引擎的死锁问题
- TCP三次握手/四次挥手详解
- 17.⼿势识别器
- NSString的常用方法
- 自定义线性及非线性存储的队列实现
- tomcat登陆它的manager
- 16
- 学习没有捷径
- iOS开发中@property的属性weak nonatomic strong readonly