Конфликтующие транзакции вызывают странное поведение - PullRequest
0 голосов
/ 11 октября 2019

У меня есть приложение, которое записывает сделки купли-продажи. В ходе этого процесса суммы запасов обновляются и регистрируются. Эти запросы выполняются как транзакция. Но если 2 из этих транзакций выполняются одновременно;количество инвентаря и регистрация могут быть неправильными.

Ниже приведен пример запросов. Если они выполняются одновременно, во 2-м запросе могут отображаться те же значения, что и в 1-м запросе, в результате чего только 1 транзакция корректно обновляет количество. Журнал транзакций будет содержать обе записи, но текущее количество будет неправильным, если они будут выполняться одновременно.

Каков наилучший способ обеспечить выполнение этих транзакций таким образом, чтобы не вызывать несоответствия

INSERT INTO transaction_log(item_id, current_quantity, amount_changed) VALUES (1, 10,-1);
INSERT INTO inventory (current_quantity, item_id) VALUES (10, 1) ON DUPLICATE KEY UPDATE quantity = 10

1 Ответ

1 голос
/ 11 октября 2019

в обновлении inventory мы могли бы применить корректировку к значению, а не указывать заменяющее значение

(мы будем предполагать, что этот вопрос не относится к проблеме с INSERT дляtransaction_log таблица; добавление строк в эту таблицу работает нормально. Предположим, что проблема связана с обновлением таблицы inventory)

Мы будем предполагать, что столбец current_quantity, на который есть ссылка в списке столбцов,количество из транзакции, а столбец quantity, на который ссылается часть обновления, является рабочим значением.

В этом примере я буду ссылаться на них как на «корректировка» и «количество»".

Допустим, строка таблицы в настоящее время выглядит следующим образом:

 item_id  quantity_onhand  quantity_adjust
 -------  ---------------  ---------------
       1              100               20

Текущий инвентарный запас равен 100, а последняя примененная корректировка - 20.

Допустим, нам нужно настроить quantity_onhand на значение 10. Мы могли бы сделать что-то вроде этого:

INSERT INTO inventory (item_id, quantity_adjust) VALUES (1, 10)
ON DUPLICATE KEY
UPDATE quantity_onhand = quantity_onhand + VALUES(quantity_adjust)
     , quantity_adjust =                   VALUES(quantity_adjust)

Предполагая, что item_id является первичным ключом (или уникальным ключом), нарушенным вставкой, wМы ожидаем, что результат будет:

 item_id  quantity_onhand  quantity_adjust
 -------  ---------------  ---------------
       1              110               10

, т. е. 10 добавляется к количеству «вручную», а 10 сохраняется как последнее значение «корректировки».

Обратите внимание, что в части обновленияоператора VALUES() возвращает значение, которое было бы вставлено, если бы вставка прошла успешно.

Результат фактически эквивалентен выполнению этого оператора:

UPDATE inventory
   SET quantity_onhand = quantity_onhand + 10
     , quantity_adjust =                   10
 WHERE item_id = 1

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


Обратите внимание, что нам также нужно обработать случай, когда оператор INSERT успешно выполняется, когда строка не существует. Мы могли бы определить столбец quantity_onhand как `DEFAULT 0 (чтобы избежать сохранения значения NULL), тогда мы получили бы ноль, сохраненный в качестве суммы на руках, что, вероятно, не то, что мы хотим.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...