Deadlocks, bloqueios e MVCC
Como os bancos de dados evitam conflitos e os compromissos entre bloqueios e instantâneos.
Deadlocks, bloqueios e MVCC é uma aula grátis de SQL Interview Prep no CoddyKit. Esta é a aula 4 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de SQL Interview Prep, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de SQL Interview Prep inclui 4 aulas no total.
Como os bancos de dados realmente aplicam o isolamento
Os níveis de isolamento são a promessa; os bloqueios e o MVCC são os mecanismos que a cumprem. Os entrevistadores perguntam sobre isso para verificar se você entende o que acontece internamente quando as transações entram em conflito.
Há duas estratégias gerais:
- Pessimista (bloqueios): bloquear acessos conflitantes até que um bloqueio seja liberado.
- Otimista / MVCC: permitir que todos leiam um instantâneo consistente e detectar conflitos no COMMIT.
Esta lição aborda bloqueios, impasses e MVCC, além das vantagens e desvantagens de cada abordagem.
Bloqueios compartilhados vs. exclusivos
O bloqueio clássico usa dois modos principais:
- Bloqueio compartilhado (S) para leituras. Muitas transações podem manter simultaneamente um bloqueio compartilhado na mesma linha.
- Bloqueio exclusivo (X) para escritas. Apenas uma transação pode mantê-lo, e ele impede todos os outros bloqueios nessa linha.
A regra é: S é compatível com S, mas X não é compatível com nada. Uma operação de escrita precisa esperar todas as operações de leitura, e as operações de leitura precisam esperar uma operação de escrita.
Bloqueio explícito com SELECT FOR UPDATE
Você pode solicitar um bloqueio de escrita nas linhas que está apenas lendo, para impedir que outras transações as alterem antes de você agir. Essa é a forma padrão de evitar atualizações perdidas em um ciclo de leitura, alteração e gravação.
SELECT ... FOR UPDATE obtém bloqueios exclusivos de linha; as linhas permanecem bloqueadas até que você execute COMMIT ou ROLLBACK.
BEGIN;
-- lock the row so no one else can modify it concurrently
SELECT balance FROM accounts WHERE id = 1 FOR UPDATE;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
COMMIT; -- lock released hereO que é um impasse?
Um impasse ocorre quando duas ou mais transações mantêm bloqueios de que as outras precisam, formando um ciclo no qual nenhuma consegue prosseguir.
O caso clássico dos livros: T1 bloqueia a linha A e depois quer a linha B; T2 bloqueia a linha B e depois quer a linha A. Cada uma espera indefinidamente pela outra.
Os bancos de dados detectam isso com um grafo de espera. Quando um ciclo é encontrado, o mecanismo escolhe uma vítima e a cancela, retornando um erro de impasse para que as outras transações possam continuar.
Impasse: linha do tempo
Observe como a ordem dos bloqueios se cruza. T1 obtém a linha 1 e depois solicita a linha 2; T2 obtém a linha 2 e depois solicita a linha 1. Nenhuma libera seu bloqueio, então o mecanismo cancela uma delas.
A transação cancelada recebe um erro como deadlock detected e precisa tentar novamente. A transação sobrevivente confirma normalmente.
-- T1 | -- T2
BEGIN; | BEGIN;
UPDATE accounts SET balance=balance-10 | UPDATE accounts SET balance=balance-10
WHERE id=1; -- locks row 1 | WHERE id=2; -- locks row 2
UPDATE accounts SET balance=balance+10 | UPDATE accounts SET balance=balance+10
WHERE id=2; -- waits for T2 | WHERE id=1; -- waits for T1 -> CYCLE
-- one transaction is chosen as victim and rolled backEvitando impasses
Não é possível eliminar completamente os impasses, mas você pode torná-los raros. Respostas padrão em entrevistas:
- Ordem consistente de aquisição de bloqueios: sempre adquirir as linhas na mesma ordem (por exemplo, pelo identificador em ordem crescente). Isso rompe o ciclo.
- Manter as transações curtas: manter os bloqueios pelo menor tempo possível.
- Reduzir o isolamento quando for seguro: menos bloqueios e menos conflitos.
- Adicionar lógica de nova tentativa: as vítimas de impasses devem tentar novamente automaticamente.
A ordem consistente é a correção mais eficaz e a primeira que os entrevistadores esperam ouvir.
Granularidade dos bloqueios
Os bloqueios podem ser obtidos em diferentes escopos, o que envolve uma troca entre concorrência e sobrecarga:
- Os bloqueios no nível da linha permitem alta concorrência, mas custam mais para gerenciar.
- Os bloqueios de página ou tabela são mais baratos de acompanhar, mas bloqueiam mais transações.
Alguns mecanismos passam de bloqueios de linha para bloqueios de tabela quando uma transação acessa linhas demais (escalonamento de bloqueios). Entender isso explica por que uma grande operação UPDATE em massa pode bloquear todos de repente.
MVCC: a abordagem do instantâneo
MVCC (Controle de Concorrência Multiversão) é a forma como Postgres, Oracle e InnoDB evitam a maioria dos bloqueios de leitura. Em vez de bloquear, o banco de dados mantém várias versões de cada linha.
O principal benefício, e uma frase de efeito muito apreciada em entrevistas, é: as leituras não bloqueiam as escritas, e as escritas não bloqueiam as leituras.
Cada transação vê um instantâneo consistente de um determinado momento, enquanto as operações de escrita criam novas versões das linhas em vez de sobrescrevê-las diretamente.
Como o MVCC funciona internamente
Quando uma linha é atualizada, o MVCC grava uma nova versão e mantém a antiga. Cada versão contém metadados do identificador da transação (no Postgres, xmin e xmax) que indicam quando ela se tornou visível e quando foi substituída.
O instantâneo de uma transação decide qual versão ela verá. As versões antigas que nenhuma transação consegue mais ver se tornam tuplas inativas e são recuperadas posteriormente por um processo de limpeza. No Postgres, esse processo é o VACUUM; não executá-lo causa inchaço da tabela, uma pergunta comum de aprofundamento.
Bloqueios vs. MVCC: a relação de vantagens e desvantagens
Resuma a comparação de forma clara:
- Bloqueios puros: correção simples, mas as leituras e as escritas bloqueiam umas às outras, prejudicando a concorrência.
- MVCC: excelente concorrência de leitura e nenhum bloqueio de leitura, mas com o custo de armazenar versões e fazer limpeza (VACUUM e inchaço), além de ainda precisar de bloqueios para conflitos entre escritas.
Mesmo os mecanismos que usam MVCC aplicam bloqueios nas escritas: duas transações que atualizam a mesma linha precisam ser serializadas. O MVCC elimina a contenção entre leitura e escrita, não a contenção entre escritas.
Bloqueio otimista e colunas de versão
Além do MVCC no nível do mecanismo, as aplicações costumam adicionar bloqueio otimista para operações de leitura, alteração e gravação durante sessões longas do usuário. Você adiciona uma coluna version, faz a leitura dela e, na atualização, exige que a versão corresponda e a incrementa.
Se outra transação tiver atualizado a linha primeiro, a versão não corresponderá mais, nenhuma linha será afetada e seu código saberá que deve recarregar os dados e tentar novamente. Nenhum bloqueio é mantido enquanto o usuário pensa, portanto a concorrência continua alta. Os entrevistadores gostam dessa resposta para a pergunta: "como você lida com dois usuários editando o mesmo registro?".
-- read: SELECT id, data, version FROM items WHERE id = 1; -- version = 7
UPDATE items
SET data = 'new value', version = version + 1
WHERE id = 1 AND version = 7;
-- if rows affected = 0, someone else changed it: reload and retryVerificação rápida
Teste a principal frase de efeito sobre o MVCC.
Recapitulação: bloqueios, impasses e MVCC
Agora você consegue explicar os mecanismos por trás do isolamento:
- Bloqueios compartilhados e exclusivos coordenam o acesso;
SELECT FOR UPDATEobtém bloqueios de escrita explícitos. - Impasses são ciclos de bloqueios; o mecanismo cancela uma vítima, e uma ordem consistente de aquisição de bloqueios evita a maioria deles.
- MVCC mantém versões das linhas para que as leituras e as escritas não se bloqueiem, ao custo de limpeza (VACUUM e inchaço).
Associe esses mecanismos aos níveis de isolamento e às anomalias das lições anteriores, e você conseguirá conduzir uma entrevista completa sobre concorrência de ponta a ponta.
Perguntas Frequentes
A aula “Deadlocks, bloqueios e MVCC” é grátis?
Sim — o texto completo de “Deadlocks, bloqueios e MVCC” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de SQL Interview Prep, atualize para CoddyKit PRO. O curso de SQL Interview Prep inclui 4 aulas no total.
O que vou aprender em “Deadlocks, bloqueios e MVCC”?
Como os bancos de dados evitam conflitos e os compromissos entre bloqueios e instantâneos. Você pratica SQL Interview Prep com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar SQL Interview Prep?
Nenhuma experiência prévia é necessária. SQL Interview Prep no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 4 de 4.
Quanto tempo leva a aula “Deadlocks, bloqueios e MVCC”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de SQL Interview Prep?
Sim. Cada aula de SQL Interview Prep inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Propriedades ACID explicadas
- Os quatro níveis de isolamento
- Leituras sujas, não repetíveis e fantasmas
- Deadlocks, bloqueios e MVCC