Reservas duplicadas no PostgreSQL: transações e bloqueios para evitá-lo

Publicado em 2026-10-26 por frfrand

Evitar reservas duplicadas e condições de corrida com transações SQL

Reservas duplicadas no PostgreSQL: transações e bloqueios para evitá-lo

Resta apenas uma vaga para um tour. Dois usuários clicam em «Reservar» quase ao mesmo tempo. Se o seu backend fizer primeiro um SELECT e depois um UPDATE sem proteção, ambos podem ver disponibilidade e vender a mesma vaga.

A ideia é resolver um problema de dados ou implantação que aparece em aplicações reais. Vamos ver o conceito sem rodeios, um exemplo de implementação e o que verificar antes de levá-lo para produção.

O que fazem Transações e reservas duplicadas

As transações agrupam operações com propriedades ACID e permitem coordenar acesso concorrente. Um bloqueio de linha FOR UPDATE, uma atualização condicional atômica ou uma restrição de unicidade podem resolver diferentes modelos. O correto depende da estrutura de vagas e pagamentos.

Não basta repetir uma receita se você não entender quem lê os dados, de qual processo e com quais permissões. Em uma aplicação com reservas, faturas ou usuários, uma condição de corrida ou uma política de acesso mal feita pode ser mais grave do que uma API lenta.

Um exemplo concreto

BEGIN;
SELECT plazas_disponibles
FROM horarios
WHERE id = 42
FOR UPDATE;
-- Si plazas_disponibles >= 1, descontar y crear reserva
UPDATE horarios
SET plazas_disponibles = plazas_disponibles - 1
WHERE id = 42 AND plazas_disponibles >= 1;
-- Comprobar ROW_COUNT / RETURNING antes de confirmar
COMMIT;

Os nomes, tabelas e chaves deste exemplo são ilustrativos. Teste primeiro em um banco ou ambiente de homologação e adapte permissões, índices e versões. Quando houver operações de gravação, não execute consultas de amostra sobre dados de clientes sem revisar o que elas modificam.

Passo a passo

  1. Defina a regra de negócio: vagas máximas, reservas pendentes, expiração e pagos.
  2. Salve disponibilidade e reservas com restrições que impeçam estados impossíveis.
  3. Use uma transação curta que bloqueie ou atualize de forma condicional o recurso.
  4. Compruebe o resultado do UPDATE; se não restarem vagas, responda um erro de negócio claro.
  5. Teste duas requisições concorrentes e verifique que apenas uma consuma a última vaga.

Ao final, não fique com «o SQL não deu erro». Verifique o efeito real pela API e com testes de concorrência ou permissões, conforme o caso. Em bancos de dados, há erros que só aparecem quando dois usuários fazem algo ao mesmo tempo.

Exemplo de projeto de trabalho

No site de tours, o cliente A e o B escolhem a última vaga. Com a linha do horário bloqueada em uma transação, o segundo espera e, ao retomar, vê a disponibilidade já atualizada.

Esse cenário ajuda a distinguir desempenho de consistência. Acelerar uma consulta não adianta se permite criar duas reservas para uma única vaga, nem um banco enorme resolve se o backend permitir consultar dados de outro cliente.

O erro típico

O exemplo é um esquema simplificado; não faça pagamentos externos enquanto mantiver uma transação aberta. Separe a reserva provisória e a confirmação por webhook usando idempotência.

Também convém ter um plano de recuperação. Antes de mexer no esquema, usuários ou políticas, guarde uma cópia verificável ou migração reversível e comprove que o aplicativo possa continuar funcionando durante a mudança.

Como resolveria com ArduMaker?

Um backend Django ou FastAPI no ArduMaker pode utilizar PostgreSQL para esta lógica. A integridade se projeta na base e aplicação, não se obtém automaticamente pelo provedor VPS.

O ArduMaker permite implantar serviços a partir do Git e trabalhar com bases e processos dentro do VPS. O painel não substitui a lógica do seu aplicativo: transações, permissões e validações devem ficar corretamente projetadas no código e no banco de dados.

Três verificações antes de publicar

Integridade: se uma requisição se repetir ou falhar no meio do caminho, os dados terminam em um estado válido?

Segurança: um usuário autenticado pode acessar apenas suas informações, e a API utiliza uma identidade de base com permissões mínimas?

Recuperação: você sabe restaurar os dados e reverter a versão de código compatível se uma atualização der errado?

Se puder responder a essas três perguntas com provas, seu backend está bastante mais preparado do que quando apenas olhou se o endpoint devolvia 200.

Recursos para aprofundar

Para encerrar: escolha a solução mais simples que permita manter dados corretos, seguros e recuperáveis. O desempenho vem depois de medir.

  • PostgreSQL
  • Tutorial
  • ArduMaker

No ArduMaker

  • PostgreSQL: Instale o PostgreSQL e gerencie bancos, usuários e permissões sem linha de comando.

Continuar lendo

Todos os artigos · Planos VPS