Optimistic vs Pessimistic Locking: Como garantir integridade em sistemas concorrentes

Entenda na prática como cada modelo de bloqueio funciona, quando usar, e como aplicar em bancos relacionais e aplicações modernas.

Publicado em

Quando falamos de arquitetura de sistemas, especialmente em ambientes que lidam com múltiplos usuários acessando e atualizando dados ao mesmo tempo, o grande desafio é evitar inconsistências geradas por concorrência. Situações como dois pedidos chegando simultaneamente para o último item do estoque, dois analistas editando o mesmo registro ou duas rotinas automatizadas tentando alterar o mesmo recurso são extremamente comuns. Para impedir esse tipo de falha, bancos de dados relacionais oferecem dois modelos clássicos de controle de concorrência: Optimistic Locking e Pessimistic Locking.

O Pessimistic Locking funciona com a lógica mais intuitiva possível: antes que alguém modifique um registro, ele é imediatamente bloqueado. Assim que o primeiro processo inicia a transação, o banco impede que qualquer outro processo altere aquela linha até que o commit seja realizado. É como colocar um cadeado temporário no dado. Esse modelo garante que nenhuma operação paralela interfira no que está acontecendo, evitando completamente conflitos. É ideal para cenários críticos — movimentações financeiras, decremento de estoque único, registros que não podem sofrer edição simultânea e operações que dependem de consistência absoluta. O ponto fraco é o custo: enquanto a transação está ativa, outros processos podem ser forçados a esperar, gerando fila e aumentando o tempo de resposta sob alta carga.

Um exemplo clássico de bloqueio pessimista aparece quando realizamos um SELECT ... FOR UPDATE dentro de uma transação:

START TRANSACTION;

SELECT estoque
FROM produtos
WHERE id = 10
FOR UPDATE;

UPDATE produtos
SET estoque = estoque - 1
WHERE id = 10;

INSERT INTO pedidos (produto_id, quantidade)
VALUES (10, 1);

COMMIT;

Nesse fluxo, o primeiro processo que executar o FOR UPDATE garante exclusividade. Qualquer tentativa paralela de tocar o mesmo registro será automaticamente bloqueada até o commit. O resultado é previsível e seguro: nunca haverá oversell.

Enquanto isso, o Optimistic Locking segue uma lógica totalmente diferente. Em vez de bloquear a linha antes de editar, ele assume que conflitos são raros. Vários processos podem ler e editar o mesmo registro simultaneamente, e o banco só verifica se houve alteração no momento do commit. Para isso funcionar, normalmente existe uma coluna de versão, timestamp ou hash que representa o “estado atual” da linha. Quando o processo tenta salvar, ele atualiza apenas se a versão ainda for a mesma que ele leu. Se alguém salvou antes, a atualização falha e um conflito é detectado.

Esse modelo é muito usado em aplicações de grande escala, APIs de alta leitura ou sistemas distribuídos, pois evita a sobrecarga de manter locks ativos. Se dois processos concorrem, apenas o primeiro salva; o segundo recebe um erro e pode tentar novamente ou abortar a operação. O custo está na necessidade de resolver conflitos manualmente ou realizar retries automáticos.

Um exemplo clássico usando versão:

SELECT estoque, version
FROM produtos
WHERE id = 10;

UPDATE produtos
SET estoque = estoque - 1,
    version = version + 1
WHERE id = 10
  AND version = 5;

Se essa atualização não afetar nenhuma linha, significa que alguém alterou o registro primeiro e o conflito está detectado. A integridade é preservada sem travar nada antecipadamente.

A diferença entre os dois modelos fica ainda mais clara quando pensamos na famosa corrida por um item de estoque único. No modelo pessimista, o primeiro processo trava a linha e o segundo fica esperando até que o banco libere, garantindo que apenas o primeiro consumirá o estoque. No modelo otimista, ambos leem o valor ao mesmo tempo, mas apenas o primeiro a salvar consegue atualizar a versão. O segundo falha com conflito. Nos dois casos, o oversell é evitado; a diferença está na estratégia.

Um exemplo prático usando Laravel e bloqueio pessimista mostra exatamente esse comportamento:

DB::transaction(function () use ($productId) {
    $product = DB::table('produtos')
        ->where('id', $productId)
        ->lockForUpdate()
        ->first();

    if ($product->estoque < 1) {
        throw new Exception("Sem estoque");
    }

    DB::table('produtos')
        ->where('id', $productId)
        ->update([
            'estoque' => $product->estoque - 1
        ]);

    DB::table('pedidos')->insert([
        'produto_id' => $productId,
        'quantidade' => 1
    ]);
});

Para otimistic locking em Laravel, o exemplo muda completamente, pois a lógica se baseia em comparar versões:

$product = Produto::find($id);

$affected = Produto::where('id', $product->id)
    ->where('version', $product->version)
    ->update([
        'estoque' => $product->estoque - 1,
        'version' => $product->version + 1,
    ]);

if ($affected === 0) {
    throw new Exception("Conflito de concorrência");
}

Ambas as abordagens são válidas e garantem integridade, mas cada uma atende necessidades específicas. O bloqueio pessimista é perfeito quando a segurança absoluta é mais importante que a performance. Já o bloqueio otimista é ideal quando a performance, escalabilidade e baixa contenção são prioridade, especialmente em sistemas distribuídos. A escolha não deve ser feita apenas olhando para o banco, mas sim para o comportamento do sistema como um todo.

No fim, o arquiteto precisa entender o impacto da concorrência no seu domínio. Se o conflito representa risco, custo financeiro ou inconsistência crítica, o pessimista prevalece. Se o sistema tolera retries e conflitos são raros, o modelo otimista entrega melhor performance. Ambos, quando bem aplicados, são fundamentais para garantir operações seguras em ambientes modernos.

 

Referências

https://www.ibm.com/docs/en/rational-clearquest/10.0.7?topic=clearquest-optimistic-pessimistic-record-locking

Gunnar Correa
Gunnar Correa

Autodidata, Graduado em Desenvolvimento Web, Especialista em Tecnologias na Educação e Pós-graduando em Segurança da Informação. Começou seus estudos na área de programação quando era criança, e atualmente, está estudando desenvolvimento de jogos. Fundador da SatellaSoft, criado em 2009 com o intuito de compartilhar conhecimento de forma gratuita e inédita.

Todos os nossos cursos em promoção

Webstories



Deixe um comentário
Aguarde...