SELECT FOR UPDATE и INSERT ON DUPLICATE KEY UPDATE вызывает тупик в MYSQL при вставке той же строки - PullRequest
0 голосов
/ 07 июня 2018

Я выполняю несколько транзакций одновременно, и возникает случай, когда одна и та же строка проверяется с помощью запроса 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, потому что я веду счет на основе предыдущего результата, прежде чем результат будет обновлен.Deadlock создан из-за вставки.

Вопрос : Как я могу избежать проблемы тупика?

1 Ответ

0 голосов
/ 08 июня 2018

Обработка транзакций в InnoDB не совсем точна.Ради производительности некоторые неблокировки рассматриваются как взаимоблокировки, потому что попытка обнаружить иное не стоит затрат и редкости.

Живите с этим.Перезапустите транзакцию, которая была заблокирована.

...