【问题标题】:MySQLTransactionRollbackException: Deadlock found when trying to get lock;MySQLTransactionRollbackException:尝试获取锁时发现死锁;
【发布时间】:2016-08-11 13:29:08
【问题描述】:

我有一个表 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

也许相同的两个数据会被两个线程同时处理,两个线程都做insert动作。

但是会导致死锁吗?不知道为什么。

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

【问题讨论】:

  • 查询和插入好像不在同一个事务中。我看到你正在使用一个 dao 框架。您确定所有操作都使用相同的事务吗?如果从查询中删除 for update?
  • 你能用dev.mysql.com/doc/refman/5.7/en/innodb-deadlocks.html这里解释的方法之一检索更多关于死锁的信息吗?
  • 这里有一个关于在简单插入期间出现意外死锁的有趣解释。问题似乎与具有自动增量的主键和像您的表一样的唯一 ley 的存在有关:dba.stackexchange.com/questions/86878/…

标签: java mysql multithreading


【解决方案1】:

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

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

查看this link 了解有关 InnoDB 使用的不同类型锁的更多信息。

This link 稍微解释一下死锁。

有时几乎不可能防止这些死锁。最常见的解决方案是:

  1. 第一个选项总是以相同的顺序在表中操作
  2. 将事务的范围(持续时间)降至最低
  3. 如有必要,提前锁定(已针对您的情况自动完成)
  4. 重试事务

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-02-07
    • 1970-01-01
    • 2017-04-05
    • 1970-01-01
    • 1970-01-01
    • 2015-11-22
    • 2013-09-20
    • 2013-07-18
    相关资源
    最近更新 更多