01 - Snapshot (Instantâneos)
video: https://youtu.be/... no frontmatter da nota.Snapshot (Instantâneos)
Snapshot é uma cópia pontual de um volume de armazenamento capturada em um instante de tempo, mantida na camada de storage e não na camada do banco de dados. Ele registra o estado dos blocos físicos do disco no momento da captura, e não o conteúdo lógico de tabelas e linhas, e por isso é criado em segundos ou minutos mesmo em volumes de terabytes. Em produção, o snapshot é o mecanismo padrão de backup de bancos gerenciados e de instâncias self-hosted em nuvem, porque desloca o custo de cópia do horário da captura para o momento em que um bloco muda. A relevância operacional é direta: é o que torna viável tirar um backup por hora de um banco grande sem saturar o I/O e sem travar as consultas. Entender o que o snapshot promete, e principalmente o que ele não promete em termos de consistência, é pré-requisito para desenhar qualquer estratégia de recuperação realista.
Conceito e funcionamento interno
Um snapshot não copia todos os dados no instante da captura. O mecanismo dominante é o copy-on-write (COW): na captura, o storage apenas cria uma tabela de metadados que aponta para os blocos originais, e a cópia real de um bloco acontece somente quando ele é modificado depois do snapshot, pois a versão antiga é preservada antes da escrita passar por cima.
A variante redirect-on-write (ROW) inverte a lógica: escritas novas vão para blocos novos, e o snapshot mantém o ponteiro para os blocos originais intocados. EBS da AWS, LVM, ZFS, Btrfs e os storages SAN corporativos implementam uma dessas variantes, e o efeito observável é o mesmo: captura quase instantânea e crescimento do consumo conforme os dados mudam.
O custo aparece depois da captura, não durante. Quanto mais o volume muda em relação ao snapshot, mais blocos antigos precisam ser retidos, e o I/O de escrita ganha uma sobrecarga extra para gerenciar os ponteiros. Por isso a frequência de snapshots precisa ser calibrada com a taxa real de churn dos dados, não com o tamanho do banco.
O primeiro snapshot é geralmente uma cópia completa e os seguintes são incrementais: apenas os blocos alterados desde o anterior são gravados. A cadeia formada depende de todos os elos anteriores, e deletar um snapshot do meio da cadeia força o storage a consolidar dados nos vizinhos, o que pode levar tempo e consumir I/O.
É importante notar o que o snapshot é e o que ele não é. Ele não é um backup transferido para fora do volume: enquanto não for copiado para outro destino, vive na mesma infraestrutura dos dados originais e herda parte dos mesmos riscos. Ele também não é portátil entre engines nem entre arquiteturas: um snapshot de disco de um servidor PostgreSQL só faz sentido para outra instância com a mesma versão do binário e layout compatível de arquivos.
Snapshot versus dump lógico
A comparação com o dump lógico (pg_dump, mysqldump, expdp) define a posição do snapshot na estratégia de backup. Os dois mecanismos respondem a perguntas diferentes e são complementares, não concorrentes.
| Aspecto | Snapshot (storage level) | Dump lógico |
|---|---|---|
| Camada que executa | Storage, SAN, EBS, ZFS | Motor do banco de dados |
| Tempo de captura | Segundos a minutos, quase independente do tamanho | Proporcional ao volume de dados, horas em bancos grandes |
| Custo durante a captura | I/O de metadados, quase nulo | Leitura completa de todos os dados |
| Granularidade de restauração | Volume inteiro, instância inteira | Banco, schema ou tabela específica |
| Consistência de transações | Requer coordenação (flush, quiesce) | Garantida nativamente pelo dump |
| Compatibilidade entre versões | Restaura na mesma versão de engine | Restaura em versões mais novas |
| Proteção contra corrupção lógica | Reproduz a corrupção se ela já estava em disco | Dados corrompidos podem ser filtrados na leitura |
| Custo de armazenamento | Incremental, eficiente em churn baixo | Proporcional ao tamanho lógico dos dados |
A leitura prática da tabela: snapshot é o mecanismo de rotina, rápido e barato, e o dump lógico é a segurança para migrações e para corrupção que se espalhou silenciosamente por semanas. Arquiteturas maduras mantêm os dois, com janelas de retenção diferentes.
Um ponto que costuma passar despercebido é a atomicidade por bloco. O snapshot é atomicamente consistente no nível do volume: ou o bloco está na versão anterior, ou na posterior, nunca no meio de uma escrita parcial. Isso elimina o risco de página corrompida por cópia a quente com cp, que era o erro clássico antes dos snapshots, e é exatamente por isso que o problema residual se concentrou na consistência transacional entre volumes, tema da seção seguinte.
Consistência do snapshot: o problema central
O snapshot captura blocos de disco em um instante, mas um banco de dados escreve continuamente em dezenas de arquivos: datafiles, WAL, redo logs, tablespaces. Capturar tudo em um estado transacionalmente válido exige coordenação, e é aqui que a maioria dos desastres silenciosos nasce.
A técnica clássica é o ciclo de quiesce: pausar brevemente as escritas do banco, forçar o flush de todos os buffers sujos para o disco, capturar o snapshot de todos os volumes envolvidos e retomar as escritas. A janela de pausa é curta, tipicamente segundos, porque a cópia em si é instantânea.
O PostgreSQL expõe esse ciclo com as funções pg_backup_start e pg_backup_stop (pg_start_backup e pg_stop_backup antes da versão 15), que registram no WAL um marcador de início e de fim e garantem que o snapshot entre eles seja recuperável. O MySQL/InnoDB exige lockdown de instância ou réplica de backup para o mesmo efeito.
# Ciclo completo de snapshot consistente em Linux com LVM
# 1. Sincroniza o cache do kernel para o disco
sync
# 2. Congela o filesystem e força o flush do banco
# (executa o flush checkpoint dentro do banco antes, ex.: CHECKPOINT;)
fsfreeze -f /var/lib/postgresql
# 3. Captura o snapshot do volume, operação de segundos
lvcreate --size 10G --snapshot --name db_snap /dev/vg0/db_data
# 4. Descongela o filesystem, as escritas voltam imediatamente
fsfreeze -u /var/lib/postgresql
# 5. O snapshot agora pode ser montado e copiado para outro destino
mount -o ro /dev/vg0/db_snap /mnt/snap
Quando o banco roda sobre múltiplos volumes, a consistência exige que todos os snapshots sejam atômicos entre si, o que na prática significa um grupo de consistência no nível do storage. Capturar volume por volume em momentos diferentes produz um conjunto irreparável, pois o WAL de um instante é aplicado sobre datafiles de outro.
Frequência de captura e RPO
A frequência de snapshots define o RPO máximo tolerado quando o snapshot é a única camada de proteção. Um banco com snapshot a cada 6 horas perde, no pior caso, 6 horas de escritas; com snapshots por hora, a janela cai para 1 hora. Essa aritmética simples é o argumento decisivo para combinar snapshots com PITR, que reduz o RPO a minutos.
A frequência tem limites práticos: cada captura pausa brevemente as escritas no ciclo de quiesce, e milhares de snapshots por dia não são viáveis nem desejáveis. A combinação típica de produção é snapshots frequentes por horas (2 a 6) como base recuperável, arquivamento contínuo de WAL/redo como camada de granularidade fina e um snapshot por dia como âncora de cadeia.
Snapshot incremental e retenção
Snapshots incrementais tornam viável capturar múltiplas vezes ao dia sem custo proporcional. A retenção, porém, forma uma cadeia: restaurar o snapshot de sexta às 14h exige os blocos de todos os snapshots da cadeia, e a política de retenção precisa respeitar essa dependência.
A prática de produção organiza a retenção em camadas, por exemplo: snapshots por hora retidos 24 horas, diários retidos 7 dias, semanais retidos 4 semanas e mensais retidos 12 meses. Essa pirâmide equilibra granularidade recente com compliance antigo, e cada camada é um snapshot de cadeia própria quando a plataforma não consolida automaticamente.
Políticas de expiração devem ser declarativas e automáticas, executadas pela plataforma (lifecycle do EBS, policies do snapshot manager) e não por scripts manuais de cron esquecidos. Snapshots órfãos, sem cadeia completa ou sem dono, acumulam custo sem oferecer recuperabilidade.
Aplicação prática em produção
Em nuvem, o snapshot é operado por API. O exemplo a seguir cobre o ciclo de captura, cópia entre regiões e expiração no EBS, o mesmo padrão usado por qualquer automation de backup.
# Captura snapshot do volume anexado à instância, com etiqueta de rastreio
aws ec2 create-snapshot \
--volume-id vol-0abc123def456 \
--description "backup diario db-01" \
--tag-specifications 'ResourceType=snapshot,Tags=[{Key=rotation,Value=daily}]'
# Copia o snapshot para outra regiao, camada da estrategia 3-2-1
aws ec2 copy-snapshot \
--source-region sa-east-1 --source-snapshot-id snap-0123456789 \
--region us-east-1 --description "copio DR us-east-1"
# Exclui snapshots de rotacao diaria com mais de 7 dias (executado por scheduler)
aws ec2 describe-snapshots \
--owner-ids self \
--filters "Name=tag:rotation,Values=daily" \
--query 'Snapshots[?StartTime<=`2024-01-01`].[SnapshotId]' --output text
Em bancos self-hosted sobre LVM ou ZFS, o snapshot local é o primeiro estágio: captura-se o volume, monta-se em modo somente leitura e extrai-se daí um dump lógico ou uma cópia para object storage. O snapshot elimina a necessidade de pausar o banco durante a cópia inteira, reduzindo a janela de quiesce a segundos.
Restauração e tempo de restore
Restaurar um snapshot cria um novo volume, e o tempo dessa operação tem armadilhas conhecidas. No EBS, o volume restaurado é lazy-loaded: a instância pode subir em minutos, mas cada bloco não presente em cache é buscado do S3 no primeiro acesso, penalizando o desempenho inicial.
Para bancos de produção que precisam voltar a operar com desempenho pleno, a plataforma oferece pré-busca (fast snapshot restore no EBS, com custo alto por zona) ou a alternativa de restaurar e deixar o banco aquecer. O RTO real precisa ser medido com teste de restore, não estimado pelo tempo reportado de criação do volume.
O fluxo de restauração em si é mecânico: desanexar o volume antigo (ou provisionar um novo), criar o volume a partir do snapshot na mesma zona de disponibilidade, reanexar e iniciar o banco com o WAL/redo disponível para acertar o ponto de recuperação. Ensaio periódico desse fluxo em ambiente isolado é o único dado confiável de RTO.
A ordem das operações na restauração importa. Em bancos com réplicas, a instância primária deve voltar primeiro, com a replicação reiniciada a partir do novo estado; subir uma réplica antiga sobre dados restaurados destrói a topologia ou força reseed completo. Em clusters de storage compartilhado, o snapshot deve ser restaurado com os nós parados, e nunca em um volume montado por serviços em execução.
Limitações que precisam de outra camada
O snapshot protege contra perda de infraestrutura, não contra todos os vetores de destruição de dados. Reconhecer os limites evita a falsa sensação de segurança que só aparece quando o incidente acontece.
- Corrupção lógica silenciosa: um UPDATE sem WHERE que roda por horas antes de ser percebido já está gravado em todos os snapshots recentes; a recuperação exige PITR para um instante anterior ou um dump antigo.
- Ransomware e credenciais comprometidas: snapshots acessíveis pela mesma conta comprometida podem ser deletados em massa; a defesa é isolamento de conta, imutabilidade (retention lock) e cópia cross-account.
- Erro de aplicação propagado: se o código novo grava dados inválidos desde o deploy de segunda-feira, o snapshot de terça reproduz o problema; detecção e janela de retenção adequada são parte da resposta.
- Deleção acidental na própria plataforma: contas com permissão ampla deletam snapshots junto com volumes; políticas de retenção mínima bloqueiam a deleção dentro da janela configurada.
- Perda da conta de nuvem inteira: snapshots vivem na conta, e a conta é o limite de confiança; a cópia para conta administrativa separada é o único antídoto real.
A regra mental de fechamento: o snapshot responde a perda, travamento e corrupção de infraestrutura em janelas de horas; para erros lógicos em janelas de minutos, a resposta é o PITR detalhado no arquivo seguinte.
Erros comuns e boas práticas
- Tirar snapshot sem flush nem quiesce e descobrir na recuperação que o banco não sobe; padronizar o ciclo sync, fsfreeze e captura, ou usar as APIs de backup do próprio banco.
- Snapshot de apenas um volume em instâncias multi-volume; usar grupos de consistência ou capturar todos os volumes no mesmo instante coordenado.
- Tratar o tempo de criação do snapshot como RTO; medir o restore real, incluindo lazy-load e tempo de recovery do banco ao subir.
- Não testar a cadeia incremental: um elo corrompido invalida tudo que vem depois; restaurar snapshots aleatórios da pirâmide de retenção mensalmente.
- Deixar snapshots acumularem sem política declarativa; configurar lifecycle com etiquetas de rotação e alerta de custo por volume órfão.
- Confiar apenas na mesma conta e região; copiar snapshots para conta separada e região distinta como camada de proteção contra falhas administrativas.
- Não etiquetar snapshots com metadados de rotação e origem; sem etiqueta, a automação de expiração não distingue cadeias e o custo cresce em silêncio.
- Documentar e ensaiar o runbook de restore, incluindo quem aciona, quais credenciais são necessárias e qual é a sequência exata de passos; backup não ensaiado é estimativa, não capacidade.