В настоящее время я сталкиваюсь с проблемой и ломаю себе голову над ней (хотя, возможно, я переборщу с ней).
В настоящее время у меня есть таблица в моей базе данных SQL с некоторыми продуктами и количеством на складе. Люди могут посетить страницу продукта или заказать ее (или обновить, если вы являетесь администратором). Но теперь я боюсь гоночных условий.
Процесс заказа происходит следующим образом:
1) Сессия начинает транзакцию.
2) Получает текущее количество доступных единиц.
3) Проверяет, доступна ли сумма для заказа, и вычитает сумму.
4) Обновляет таблицу продуктов новым значением "общая сумма". Вот очень короткий код (без использования подготовленных операторов и т. Д.).
BEGIN;
SELECT amount FROM products WHERE id=100;
$available=$result->fetch_array(MYSQLI_NUM)[0];
if($order<=$available){
$available-=$order;
UDPATE products SET amount=$available WHERE id=100;
}
//error checking and then ROLLBACK or COMMIT
Мой вопрос сейчас:
Что я делаю, чтобы предотвратить грязные показания на шаге 2 и, таким образом, запись неправильных значений на шаге 4?
пример: если 1 человек заказывает 10 товаров А, и пока он находится на шаге 3, второй человек также заказывает 5 товаров А. Поэтому на шаге 2 он по-прежнему получит «старое» значение и будет работать с что, и, таким образом, восстанавливает неправильный номер на шаге 4.
Я знаю, что могу использовать «SELECT .... FOR UPDATE», который установит эксклюзивную блокировку строки, но это также мешает обычному пользователю, который просто проверяет доступность (на странице продукта), предотвращать мгновенную загрузку , в то время как я предпочитаю, чтобы они загружали страницу быстрее, чем на второй точный инвентарь. Поэтому я хочу, чтобы блокировка чтения применялась только к клиентам, которые обновят значение в той же транзакции.
Возможно ли то, что я хочу, или мне нужно работать с тем, что у меня есть?
Заранее спасибо!