Есть интернет-магазин, в базе данных есть таблица products(id,name,details,qty).
Есть форма заполнения заявки, где указывается количество товара.
Написал перед уменьшением количества товара и добавления заказа, стандартную проверку на php, проверяющую, что количество требуемого товара, не превышает количество товара на складе. И всё вроде работает.
До тех пор пока пользователи в интернете нажмут на кнопку заказать одновременно( вероятность мала, но есть). Тогда количество товара товара после 1-го заказа ещё не успеет уменьшится, и 2-ой заказ так же пройдёт проверку, и получится что пользователи закажут больше товара чем есть на складе.
Для решения этой проблемы посоветовали использовать блокировки. Вопрос в том какие блокировки использовать?
Как я понимаю всю таблицу блокировать не стоит, достаточно использовать блокировку отдельной записи, с которой работаем.
С помощью какой команды это делается? нашёл SELECT ... FOR UPDATE, но она видимо не совсем подходит.
1. mag1K - 16 Мая, 2012 - 18:40:20 - перейти к сообщению
2. DeepVarvar - 16 Мая, 2012 - 18:49:21 - перейти к сообщению
3. caballero - 16 Мая, 2012 - 19:04:21 - перейти к сообщению
Цитата:
Для решения этой проблемы посоветовали использовать блокировки. Вопрос в том какие блокировки использовать?
глупый совет
никакими блокировками и транзакциями это не делается
и твою проблему не решает никаким каком
единственный способ - резервировать товар (добавть поле в таблицу или специальную таблицу чтобы к юзеру привязать) и возвращать количество без резервированных. В случает незавершения покупки - резевирование отменяется
Цитата:
получится что пользователи закажут больше товара чем есть на складе.
они что заказывают весть товар что видят? или заказывают сколько надо? какое дело юзеру сколько там на складе
проблема на самом деле может быть только если осталось несколько штук. То есть она еще более маловероятна если следить за состоянием склада
4. DeepVarvar - 16 Мая, 2012 - 19:17:14 - перейти к сообщению
caballero пишет:
Я скинул к тому что атомарные операции апдейта и инсерта, как написано, лочат все сами, и тот кто читает из таблицы становится в очередь и ожидает, пока таблица разлочится.никакими блокировками и транзакциями это не делается
Однако было дело, ставил эксперимент. Создал таблицу на 10 записей (id, name) id не уникальный, не автоинкремент, просто INT.
Добавляя в конец удалял первую запись.
Писатель:
CODE (SQL):
скопировать код в буфер обмена
скопировать код в буфер обмена
- UPDATE tbl SET id = id -1; INSERT INTO tbl (id, name) VALUES (10, 'что-то там');
Читатель:
Так вот при больших скоростях в цикле или при большом кол-ве "писателей", "читатель" получает не верные данные, дублирование id, больше 10 записей и прочие неинтересности...
Это связано и с кешем мускуля и с тем что в эксперименте у писателя не одна операция, а две.
Лечение: делать все одним запросом.
caballero пишет:
А вот вопрос в принципе верный. Или вы считаете что синхронизация данных не важна?
глупый совет