Mysqli / PHP предотвращает некоторые грязные чтения - PullRequest
0 голосов
/ 27 июня 2018

В настоящее время я сталкиваюсь с проблемой и ломаю себе голову над ней (хотя, возможно, я переборщу с ней).

В настоящее время у меня есть таблица в моей базе данных 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», который установит эксклюзивную блокировку строки, но это также мешает обычному пользователю, который просто проверяет доступность (на странице продукта), предотвращать мгновенную загрузку , в то время как я предпочитаю, чтобы они загружали страницу быстрее, чем на второй точный инвентарь. Поэтому я хочу, чтобы блокировка чтения применялась только к клиентам, которые обновят значение в той же транзакции.

Возможно ли то, что я хочу, или мне нужно работать с тем, что у меня есть? Заранее спасибо!

1 Ответ

0 голосов
/ 27 июня 2018

Существует два способа решения проблемы:

  1. Вы можете использовать функцию в MySQL, которая обновляет запасы и выдает ошибку «Извините, ваш продукт просто вышел из запаса!», Всякий раз, когда остаток после вычета становится меньше 0.

ИЛИ (предпочтительный способ)

  1. Вы можете использовать блокировку в MySQL. В этом случае это должна быть блокировка записи. Блокировка записи должна отключить другие запросы на чтение (от второго лица), пока блокировка не будет снята (от первого лица).

Надеюсь, это поможет вам!

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