Произошла ошибка взаимоблокировки при добавлении и обновлении записи одновременно - PullRequest
0 голосов
/ 04 мая 2018

В настоящее время мы разрабатываем проект, который имеет много транзакций. Пользователи добавляют порядок в таблицу очередей, а другие сценарии обрабатывают транзакцию. при добавлении транзакции и механизма очередей возникает тупиковая ошибка.

таблица очередей

CREATE TABLE `order_queue` (
    `OrderId` BIGINT(20) UNSIGNED NOT NULL,
    `State` TINYINT(3) UNSIGNED NOT NULL COMMENT '1=adding, 11=proccessing, 2=complete',
    `EngineId` SMALLINT(5) UNSIGNED NOT NULL,
    `AddTime` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (`OrderId`),
    INDEX `State` (`State`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB;

добавление транзакций

$db->beginTransaction();
$db->exec("INSERT INTO order_queue (OrderId, State, EngineId) VALUES ({$OrderId}, 1, 0)");
$db->commit();

и, наконец, у нас есть три механизма очередей, которые получают транзакцию и отправляют другие системы

$db->query("UPDATE order_queue SET State=11,EngineId={$EngineId} WHERE State=1 LIMIT 1");

$qOrder = $db->query("SELECT * FROM order_queue 
            WHERE State=11 AND EngineId={$EngineId}")->fetch();

echo $qOrder->OrderId;
//send the order to other systems
$db->exec("UPDATE order_queue SET State=2 WHERE OrderId={$qOrder->OrderId}");

если этот скрипт работает одновременно, возникают самые любимые ошибки

SQLSTATE[40001]: Serialization failure: 1213 Deadlock found when trying to get lock; try restarting transaction

Я попробовал несколько способов, во-первых, проверить AddTime, во-вторых, изменил State после $db->commit(); строки и т. Д., Но проблема не решена.

Если бы вы были мной, что бы вы делали? Какой метод самый лучший?

1 Ответ

0 голосов
/ 04 мая 2018

Вы можете попробовать использовать «блокировку в режиме совместного использования», как показано ниже

$db->query("UPDATE order_queue SET State=11,EngineId={$EngineId} WHERE State=1 LIMIT 1");

$qOrder = $db->query("SELECT * FROM order_queue 
            WHERE State=11 AND EngineId={$EngineId} lock in share mode")->fetch();

echo $qOrder->OrderId;
//send the order to other systems
$db->exec("UPDATE order_queue SET State=2 WHERE OrderId={$qOrder->OrderId}");
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...