SELECT FOR UPDATE和INSERT ON DUPLICATE KEY UPDATE在同一行插入时导致MYSQL中出现死锁

时间:2018-06-07 16:15:02

标签: mysql transactions innodb deadlock

我正在同时执行多个事务,并且当通过SELECT FOR UPDATE查询检查相同行并且使用INSERT ON DUPLICATE KEY UPDATE插入或更新它时会出现这种情况。但这会导致死锁。

这是表格架构

CREATE TABLE `t` (
  `a` varchar(40) NOT NULL,
  `b` date NOT NULL,
  `c` enum('a','b') COLLATE utf8_bin NOT NULL,
  `d` char(12) NOT NULL,
  `e` TINYINT(1) UNSIGNED NOT NULL,
  PRIMARY KEY (`a, `b`, `c`, `d` )
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

以下是交易操作。

在事务1中:

Start Transaction;

SELECT  *
FROM t
WHERE
    a= '123'
        AND `b` = '2017-01-01'
        AND c= 'a'
        AND d= '1'
FOR UPDATE;

INSERT INTO t
(`a`, b, `c` , d, e)
VALUES ('123', '2017-01-01', 'a' , '1'  , '2')
ON DUPLICATE KEY UPDATE `e` = '2';

Commit;

在交易2中:

Start Transaction;

SELECT  *
FROM t
WHERE
    a= '123'
        AND `b` = '2017-01-01'
        AND c= 'a'
        AND d= '1'
FOR UPDATE;

INSERT INTO t
(`a`, b, `c` , d, e)
VALUES ('123', '2017-01-01', 'a' , '1'  , '2')
ON DUPLICATE KEY UPDATE `e` = '2';

Commit;

当两个事务都运行select for update并且其中一个事务尝试插入行时发生死锁。

注意:我需要SELECT FOR UPDATE,因为在结果更新之前,我会根据之前的结果保持计数。由于插入而创建死锁。

问题:如何避免死锁问题?

1 个答案:

答案 0 :(得分:0)

InnoDB的交易处理并不完全准确。为了性能,一些非死锁被视为死锁,因为发现其他方面的努力不值得花费和稀缺。

和它一起生活。重新启动被破坏的事务。