Вашият проблем се свежда до въпроса "какво трябва да бъде заключването на синхронизацията" . От въпроса ви изглежда, че резервацията не е резервация на конкретен артикул. Но нека приемем, че потребител резервира конкретна хотелска стая, така че трябва да решите два проблема:
- предотвратяване на свръхрезервиране (напр. резервиране на едно и също нещо за двама души)
- предотвратяване на грешно изчисляване на състоянието на паралелния акаунт
Така че, когато потребител стигне до момент, в който е на път да натисне потвърди бутон, това е възможен сценарий, който можете да приложите:
-
започнете транзакцията
-
заключете потребителския запис, така че паралелните процеси да бъдат блокирани
SELECT * FROM user FOR UPDATE WHERE id = :id
-
проверете отново баланса на сметката и хвърлете изключение / връщане назад, ако няма достатъчно средства
-
заключете артикула за резервиране, за да предотвратите свръхрезервиране
SELECT * FROM room FOR UPDATE WHERE id = :id
-
проверете отново наличността на резервацията и изхвърлете изключение / връщане назад, ако артикулът вече е резервиран
-
създайте запис за резервация и извадете средства от сметката на потребителя
-
извършване на транзакция (всички ключалки ще бъдат освободени)
Ако във вашия случай не е необходимо да проверявате за свръхрезервация, просто пропуснете/игнорирайте стъпки 4 и 5.