Подходит ли SELECT ... FOR UPDATE для сценария одноразового использования строки? - PullRequest
0 голосов
/ 15 марта 2012

У меня есть таблица promo_codes, которую можно активировать с помощью веб-приложения. Существует столбец state, который может быть 0 для неактивированного или 1 для активированного. Если я запускаю транзакцию с

SELECT FROM promo_codes WHERE state=0 LIMIT 1 FOR UPDATE;
UPDATE promo_codes SET state=1 WHERE id = ?;

Что происходит со второй запущенной транзакцией:

SELECT FROM promo_codes WHERE state=0 LIMIT 1 FOR UPDATE;

Он просто возвращает следующую строку или блокируется до первой транзакции?

На самом деле я начал думать о том, чтобы просто установить блокировку на основе идентификатора строки в redis, потому что для меня очевидно, как это будет работать, и я знаю, что это не создаст проблем с производительностью в MySQL, но с другой стороны должен быть чистый и эффективный способ сделать эту работу исключительно в SQL. Может быть, я мог бы сначала использовать UPDATE ... LIMIT 1, но как мне вернуть идентификатор промокода в этом случае?

1 Ответ

0 голосов
/ 15 марта 2012

SELECT для модификаторов UPDATE и LOCK IN SHARE эффективно работают в режиме READ-COMMITTED, даже если текущий режим изоляции - REPEATABLE-READ. Это сделано потому, что Innodb может заблокировать только текущую версию строки. Подумайте об аналогичном случае и удаляемой строке. Даже если бы Innodb смог установить блокировки в строках, которых больше не существует - это вам поможет? Не совсем - например, вы можете попытаться обновить строку, которую вы только что заблокировали, с помощью SELECT FOR UPDATE, но эта строка уже пропала, поэтому вы получите довольно неожиданную ошибку при обновлении строки, которую, как вы думали, вы заблокировали успешно. В любом случае, все сделано так, что все остальные решения будут еще более хлопотными.

LOCK IN SHARE MODE на самом деле часто используется для обхода многовариантности и обеспечения того, чтобы мы считывали большинство текущих данных, а также для гарантии того, что их нельзя изменить. Это, например, может быть использовано для считывания набора строк, вычисления новых значений для некоторых из них и записи их обратно. Если мы не будем использовать LOCK IN SHARE MODE, у нас могут возникнуть проблемы, поскольку строки могут обновляться до того, как мы напишем им новые значения, и такое обновление может быть потеряно.

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