Home Comunidade Eventos YouTube Networks Desafios // produtos Academy News CTI | CVE Contato

01 - Snapshot (Instantâneos)

#backup#copy-on-write#restauracao#snapshot#storage
video explicativo
Video explicativoEspaco reservado para o video desta anotação — adicione 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.