Как не допустить двойную трату денег на балансе пользователя?
В сайте существуют 2 таблицы
balances
id, owner_id, total
и
orders
id, product_id, price, created_timestamp
Пользователь заходит на сайт и нажимает под каким-то товаром кнопку купить, отправляется запрос на сервер, он обрабатывается скриптом php
в этом коде есть фрагмент
$query = pg_query("SELECT total from balances where owner_id = '$user_id' LIMIT 1;");
$total = pg_fetch_array($pg_query($query))[0];
if ($total >= $product_price){
$query = "UPDATE balances set total = total-'$product_price' where owner_id = '$user_id';
INSERT into orders (product_id, price, created_timestamp) VALUES ('$product_id','$product_price','$timestamp');";
}
мне кажется этот фрагмент кода может стать уязвимостью в сайте,в случае если пользователь быстро отправит условную 1000 запросов к серверу, то т.к. эти запросы обрабатываются параллельно, то несколько запросов могут получить баланс пользователя до его изменения и в итоге могут создаться два и более заказов, а баланс пользователя уйдёт в минус
мои знания в как в базах , так и в языках программирования достаточно скромны, поэтому мне не приходит в голову ни одного решения кроме как создания сервиса, с которым этот скрипт будет соединяться, чтобы передать запрос. А этот сервис уже проверяет балансы и добавляет заказы, используя только один поток этот вариант мне не очень нравится, тк это очень сильно режет максимальную нагрузку на сайт
хотелось бы каким-то образом заблокировать строку балансов этого пользователя для чтения и изменения одним и тем же запросом с SELECT total и разблокировать только после вычитания цены товара
Возможно ли это как-то сделать или подойдёт какой-то другой способ?