MySQLTransactionRollbackException:尝试获取锁定时发现死锁;

时间:2016-08-11 13:29:08

标签: java mysql multithreading

我有一张表trade_order:

 CREATE TABLE `trade_order` IF NOT EXISTS `buyer_order` (
 `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
 `order_no` varchar(30) NOT NULL DEFAULT '',
 `name` int(11) unsigned NOT NULL DEFAULT '0',
 PRIMARY KEY (`id`),
 UNIQUE KEY `order_no` (`order_no`),
 )

现在我想将数据插入表trade_order。我是这样做的:

transaction begin.
===
result = select * from order_table where order_no = #{orderNo} for update 
if(result is null){
    insert into trade_order (order_no,name) values (orderNo,name)
}
else{
    update trade_order set name = #{name} where order_no = #{orderNo}
}
===
transaction end.

但我得到了死锁:

 org.springframework.dao.DeadlockLoserDataAccessException: 
 ### Error updating database.  Cause:      com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock      found when trying to get lock; try restarting transaction
 ### The error may involve      com.youzan.trade.process.datasync.dal.dao.OrderDAO.insert-Inline
 ### The error occurred while setting parameters
 ### SQL: insert into trade_order ( order_no, name )  values ( ?,         ?,  )
 ### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction
 ; SQL []; Deadlock found when trying to get lock; try restarting transaction; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction

两个线程可能同时处理相同的两个数据,并且两个线程都执行插入操作。

但它会导致deadLock吗?我想知道为什么。

(mysql事务隔离级别是RR,InnoDB引擎)

1 个答案:

答案 0 :(得分:0)

这是一个古老的问题,但也许有人觉得它有用。

原因可能是MySQL的InnoDB使用插入意图锁,该意图锁在插入或更新时会锁定一组行。

检查this link以获得有关InnoDB使用的不同类型的锁的更多信息。

This link解释了一些有关死锁的问题。

有时候,防止这些僵局几乎是不可能的。最常见的解决方案是:

  1. 第一个选项始终以相同的顺序在表中运行
  2. 将交易范围(持续时间)最小化
  3. 如有必要,请提前锁定(已根据您的情况自动完成)
  4. 重试交易