Условия гонки базы данных - PullRequest
3 голосов
/ 24 марта 2012

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

  • Пользователь 1 выбирает поле, скажем, numStock, которое равно 3
  • Пользователь 2 также выбирает numStock, который по-прежнему 3
  • Пользователь 1 уменьшает numStock (в приложении) и устанавливает его в базу данных равным 2.
  • Пользователь 2 также уменьшает numStock (в приложении) и устанавливает его в базу данных равным 2.

В этом примере поле numStock должно было стать 1, но вместо этого было установлено значение 2 из-за гонки между пользователями.

Так что, конечно, можно использовать блокировки, но я подумал о другом способе обработки этого - прохождение всех деталей строки в качестве критерия WHERE. Позвольте мне объяснить ...

В приведенном выше примере коды SQL могут выглядеть следующим образом:

// выберите

SELECT itemID, numStock FROM items WHERE itemID = 45

// обновление

UPDATE items SET numStock = 2 WHERE itemID = 45

Моя идея по разрешению гонки:

// выберите

SELECT itemID, numStock FROM items WHERE itemID = 45

// обновление

UPDATE items SET numStock = 2 WHERE itemID = 45 AND numStock = 3

Таким образом, запрос проверяет, изменились ли данные с тех пор, как он ВЫБЕРИЛ данные. Итак, мой вопрос: (1) Будет ли это [всегда] работать? и (2) это лучший вариант по сравнению с механизмами блокировки базы данных (например, MySQL Transactions)?

Спасибо за ваше время.

Ответы [ 2 ]

5 голосов
/ 24 марта 2012

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

Конечно, вам нужен способ повторить транзакцию.И если вероятность неудачи очень высока, она может стать неэффективной.Но в большинстве случаев это работает просто отлично.

0 голосов
/ 27 августа 2018

Как насчет выбора и обновления в одном утверждении:

UPDATE counters SET value = (@cur_value := value) + 1 WHERE name_counter = 'XXX';

, а затем

SELECT @cur_value;

Может ли эта стратегия решить условие гонки?

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