Seu problema se resume à questão de "qual deve ser o bloqueio de sincronização" . Pela sua pergunta, parece que a reserva não é a reserva de um item específico. Mas vamos supor que um usuário esteja reservando um quarto de hotel específico, então você precisa resolver dois problemas:
- prevenir reservas em excesso (por exemplo, reservar a mesma coisa para duas pessoas)
- evitar erros de cálculo do estado da conta paralela
Então, quando um usuário chega a um ponto em que está prestes a clicar em confirmar botão, este é um cenário possível que você pode implementar:
-
iniciar transação
-
bloquear a entrada do usuário para que os processos paralelos sejam bloqueados
SELECT * FROM user FOR UPDATE WHERE id = :id
-
verifique novamente o saldo da conta e lance exceção / reversão se houver fundos insuficientes
-
bloquear o item a ser reservado para evitar overbooking
SELECT * FROM room FOR UPDATE WHERE id = :id
-
verifique novamente a disponibilidade da reserva e lance exceção/reversão se o item já estiver reservado
-
criar entrada de reserva e subtrair fundos da conta do usuário
-
transação de commit (todos os bloqueios serão liberados)
Se, no seu caso, você não precisar verificar se há overbooking, basta pular/ignorar os passos 4 e 5.