A migração que trava a tabela

Prévia grátis 3 min de leitura

A maioria das migrações é instantânea, e é por isso que as que não são pegam de surpresa. O que decide isso não é o tamanho da tabela. É se o banco precisa reescrevê-la.

O que é instantâneo no Postgres

Adicionar uma coluna anulável é instantâneo. Desde o Postgres 11, adicionar uma coluna com valor padrão constante também é: o padrão fica registrado no catálogo e não é escrito em cada linha existente.

Remover uma coluna é instantâneo. A coluna é marcada como morta, e o espaço é recuperado depois.

Renomear uma coluna ou uma tabela é instantâneo, porque só o catálogo muda.

Isso cobre a maior parte do que um arquivo de migração contém, e é por isso que as mudanças de esquema do dia a dia parecem de graça.

O que reescreve a tabela

Mudar o tipo de uma coluna geralmente reescreve a tabela, porque cada valor existente precisa ser convertido.

Adicionar uma restrição NOT NULL a uma coluna existente exige uma varredura completa, para provar que não há nulos.

Adicionar um índice sem CONCURRENTLY toma um lock que bloqueia as escritas durante toda a construção.

Mudar um valor padrão é instantâneo, mas preencher as linhas existentes para combinar com ele não é, e essa diferença pega as pessoas o tempo todo.

flowchart TB
  M["uma migração"] --> C{"ela reescreve linhas?"}
  C -->|não| I["só catálogo. instantânea, em qualquer tamanho"]
  C -->|sim| L["uma reescrita sob ACCESS EXCLUSIVE"]
  L --> B["toda leitura e escrita na tabela espera"]
  B --> S["a duração escala com o número de linhas"]

O problema é o lock, mais que a duração

Uma reescrita segura um lock ACCESS EXCLUSIVE, que bloqueia toda leitura e toda escrita naquela tabela até terminar.

Dez segundos disso numa tabela movimentada são uma queda. As requisições se enfileiram atrás, as conexões se acumulam, e o pool se esgota muito antes de a migração terminar.

É pior do que parece. O Postgres enfileira os pedidos de lock em ordem, então um ALTER TABLE esperando o próprio lock bloqueia toda query que chega depois dele. Isso inclui leituras simples que não teriam conflito. Uma migração lenta pode travar uma tabela que ela ainda nem começou a modificar.

Onde esta aplicação está

Em setembro de 2026, a maior tabela aqui era quiz_options, com cerca de 40.000 linhas, e lessons tinha 2519. Forçar uma reescrita completa de qualquer uma delas levou menos de 200 milissegundos localmente.

Então este curso não descreve um problema que esta aplicação tem. Ele descreve o problema que ela teria com cem vezes o tamanho, e as ferramentas que existem porque outras pessoas o encontraram primeiro.

Saber quais migrações são seguras é útil em qualquer escala. Saber por que as inseguras são inseguras é o que dá sentido às ferramentas das próximas lições.

Pontos-chave

  • Adicionar colunas anuláveis, adicionar padrões constantes, remover e renomear só mexem no catálogo, então são instantâneos.
  • Mudanças de tipo, NOT NULL em colunas existentes e índices não concorrentes reescrevem ou varrem a tabela.
  • Uma reescrita segura ACCESS EXCLUSIVE, bloqueando toda leitura e escrita até terminar.
  • Um ALTER TABLE em espera bloqueia as queries que chegam atrás dele, inclusive leituras inofensivas.
  • As tabelas desta aplicação são pequenas, e o raciocínio importa em qualquer tamanho.
Aula 1 de 7 · grátis

Continue com a aula 2

Como o gh-ost funciona

Como o gh-ost cria uma tabela sombra, copia em lotes, lê o log binário e troca os nomes.

Com uma conta grátis você também tem os quizzes, seu progresso e suas anotações, e a discussão.

Digite para buscar...