Есть некое приложение с бд mysql.
Есть две таблицы, одна из них с пользователями users, вторая с товаром в магазине shop.
Нужно провести запрос, в котором:
1. Снять сумму с баланса пользователя, проверив есть ли у него эта сумма на балансе
2. Поменять статус товара на ПРОДАНО.
Однако, не знаю как это сделать правильно ибо боюсь ситуации, в которой >2 одновременно посланных запроса снимут сумму с баланса пользователя дважды (баланс станет отрицательным).
То есть, во время выполнения первого запроса, после проверки наличия суммы на балансе, будет послан второй, проверка так же будет пройдена. Затем первый запрос снимет сумму с баланса, а после него и второй. Будет не очень хорошо :\
Каким образом можно быть на 100% уверенным, что такого не произойдет?
Я понимаю, что нужно блокировать таблицу, однако, как это точно сделать - не понимаю. Пытался гуглить, читал про acid и блокировки бд, но так и не могу придумать запрос, в котором все будет "как надо".
Кто то может привести пример?
Дмитрий Шицков: еще два раза перечитал статью. Или я не туда смотрю, или не о том думаю. Как мне FOR UPDATE должен помочь в проверке баланса? Мне нужно сделать SELECT FOR UPDATE для получения баланса, проверить в логике программы, а затем внести изменения в ту же строку и лок сам снимется, я правильно понял?
LoveTheBeautifulSkies: Стартуете транзакцию, проверяете баланс с for update, делаете с ним что-то, производите списания/зачисления и делаете коммит транзакции (или откат, если баланс, скажем, недостаточный). Лок после этого снимается.
LoveTheBeautifulSkies: должно быть в рамках одной транзакции и одного подключения. Если соединения прервется, транзакция откатится. Главное чтобы был отключён автокоммит, как там упоминается.