1 pontos por GN⁺ 2025-12-24 | 1 comentários | Compartilhar no WhatsApp
  • O PostgreSQL 18 combina a estratégia de cópia de arquivos (FILE_COPY) com recursos de clonagem do sistema de arquivos para clonar bancos de dados quase instantaneamente
  • Com a nova configuração file_copy_method = clone, é possível aproveitar o recurso de clonagem (FICLONE) de sistemas de arquivos modernos como XFS, ZFS e APFS
  • Nos benchmarks, ao clonar um banco de dados de 6 GB, o método tradicional WAL_LOG levou cerca de 67 segundos, enquanto o método com clone caiu para cerca de 0,2 segundo
  • O banco de dados clonado inicialmente compartilha os mesmos blocos físicos, mas em operações de escrita ocorre a separação via copy-on-write
  • Porém, a clonagem só é possível quando não há conexões ativas e há a limitação de funcionar apenas dentro de um único sistema de arquivos

Estrutura de clonagem baseada em template no PostgreSQL

  • No PostgreSQL, ao executar o comando CREATE DATABASE dbname, internamente o sistema clona o banco de dados template1 para criar o novo banco
    • Isso equivale a CREATE DATABASE dbname TEMPLATE template1
  • Em vez de template1, é possível especificar outro banco de dados, permitindo clonagem com templates personalizados
  • No PostgreSQL 18, esse sistema de templates foi expandido para uma estrutura de clonagem instantânea

CREATE DATABASE ... STRATEGY

  • Desde o PostgreSQL 15, foi introduzido o parâmetro CREATE DATABASE ... STRATEGY, permitindo escolher o método de clonagem
    • O padrão é WAL_LOG, que faz clonagem em nível de bloco por meio de Write-Ahead Log
    • Esse método reduz a carga de I/O e melhora o suporte à concorrência, mas é lento em clonagens de grande volume
  • Ao especificar STRATEGY=FILE_COPY, é possível voltar ao método tradicional de cópia de arquivos, e no PostgreSQL 18 foi adicionada uma nova opção de clonagem com base nisso

FILE_COPY e file_copy_method

  • A configuração file_copy_method do PostgreSQL 18 controla o método de cópia de arquivos no nível do sistema operacional
    • O valor padrão é copy, que lê todos os bytes e grava em um novo local
    • Ao mudar para clone, o PostgreSQL usa o recurso de clonagem do sistema de arquivos (FICLONE), permitindo clonagem instantânea sem consumo adicional de espaço
  • Sistemas de arquivos compatíveis: XFS, ZFS, APFS e ZFS no FreeBSD
  • Procedimento de configuração
    • Montar o cluster PostgreSQL sobre um sistema de arquivos compatível
    • Definir file_copy_method = clone e recarregar a configuração

Resultados de benchmark

  • Após criar um banco de testes de cerca de 6 GB (source_db), foram comparados dois métodos
    • Método WAL_LOG: 67.000 ms (cerca de 67 segundos)
    • Método FILE_COPY + clone: 212 ms
  • Com o mesmo volume de dados, foi observada uma melhora de velocidade de mais de 300 vezes
  • O banco clonado (fast_clone) quase não consome espaço adicional em disco

Como os dados clonados funcionam

  • Ao usar file_copy_method = clone, apenas os metadados do sistema de arquivos são clonados, e os dois bancos passam a compartilhar os mesmos blocos físicos
  • O tamanho do banco de dados reportado pelo PostgreSQL continua sendo o tamanho lógico (cerca de 6 GB)
  • Quando ocorrem escritas, entra em ação o copy-on-write (COW), separando as páginas afetadas
    • Páginas que contêm linhas modificadas
    • Páginas onde novos tuples são gravados
    • Páginas de índice, FSM, visibility map etc.
  • Mesmo ao executar VACUUM, ocorre separação adicional de páginas

Verificação de blocos compartilhados no XFS

  • O comando filefrag -v permite verificar se os dois bancos compartilham os mesmos blocos físicos
    • No estado inicial, todos os extents aparecem marcados como shared
    • Ao atualizar algumas linhas, os primeiros 40 blocos (cerca de 160 KB) são separados e passam a apontar para endereços físicos diferentes
    • Os demais extents continuam em estado compartilhado

Cuidados e limitações

  • Não pode haver conexões ativas no banco de origem durante a clonagem
    • Essa é uma limitação do PostgreSQL, não um problema do sistema de arquivos
    • Em ambientes de produção, é comum usar um banco de templates separado
  • A clonagem só funciona dentro de um único sistema de arquivos
    • Se houver vários tablespaces em pontos de montagem diferentes, o processo volta para cópia normal
  • Em serviços gerenciados em nuvem (AWS RDS, Google Cloud SQL etc.), esse recurso não pode ser usado porque não há acesso ao sistema de arquivos
    • Em VMs próprias ou ambientes bare metal, é possível ter controle total

Conclusão

  • O recurso file_copy_method = clone do PostgreSQL 18 usa diretamente a clonagem em nível de sistema operacional para
    reduzir drasticamente o tempo de clonagem de bancos de dados grandes
  • Em ambientes de teste, desenvolvimento e aprendizado, isso permite implementar workflows de banco de dados com clonagem e reset quase instantâneos
  • Ainda assim, é necessário projetar a operação levando em conta a restrição de conexões ativas e a exigência de um único sistema de arquivos

1 comentários

 
GN⁺ 2025-12-24
Comentários do Hacker News
  • Para quem não pode esperar ou precisa de isolamento completo de instância no PG18, criei o Velo, uma ferramenta de branching instantâneo usando snapshots do ZFS
    Funciona com qualquer versão do PostgreSQL, e cada branch tem contêiner e porta independentes
    Pode ser criado em cerca de 2 a 5 segundos para um DB de 100 GB
    A diferença em relação ao método do PG18 é que ele não compartilha uma única instância, oferecendo isolamento completo de servidor
    Link do GitHub

    • Houve reclamações em outro comentário sobre o uso do Claude Code, mas achei interessante depois de ver o vídeo de demonstração na página do GitHub
    • Hoje em dia a maior parte do software é escrita com ajuda de agentes de IA, então não entendo por que tanta reclamação. A abordagem é interessante
    • Eu também estava pensando em prototipar algo parecido com btrfs
    • Achei interessante o uso da expressão “você”, então fiquei meio surpreso ao ver gente dizendo que era plágio
  • No passado, quando a empresa migrou para RDS, construímos internamente um sistema parecido
    Como problemas aconteciam com frequência durante migrações em produção, automatizamos as etapas abaixo para evitar isso

    1. Clonar o DB do RDS ou criar uma nova instância a partir de backup
    2. Extrair o CNAME ou IP público a partir do ARN
    3. Refletir isso na configuração de conexão com o DB do app
    4. Executar a migração em um ambiente falso de produção
      Graças a esse processo, conseguimos pegar muitos bugs específicos de produção que não apareciam localmente nem no CI
      Depois automatizamos isso com um script Ruby simples, e ouvi dizer que ainda usam esse script até hoje
    • Eu também odeio esse tipo de bug de “migração que só falha em produção por causa de peculiaridades dos dados”. Já precisei cancelar releases algumas vezes por causa disso
  • Só agora descobri que a estratégia de template cloning pode ser configurada
    Usei o Neon para criar ambientes de integração em tempo real, e no meu projeto em Golang pgtestdb eu crio um DB Postgres com migração completa de schema aplicada para cada teste
    Já vi uma startup criar DBs de staging instantâneos com btrfs, e é interessante ver ideias parecidas reaparecendo
    Esse tipo de clonagem rápida e testes é uma grande vantagem do Postgres e do Sqlite, e seria ótimo se também fosse possível em Clickhouse e MySQL

  • Hoje em dia o PostgreSQL parece ter virado um DB coringa que cobre praticamente todos os usos de SQL
    E ainda é gratuito
    Fico pensando se ainda existe motivo para usar outro DB SQL

    • O Postgres é excelente, mas o MySQL facilita mais replicação master-master, e o MongoDB simplifica distribuição geográfica e sharding
      O Clickhouse é muito mais rápido para analytics, e DBs como Cassandra são vantajosos para cargas centradas em escrita
      Ou seja, cada DB ainda tem seus pontos fortes
    • Dizer que “faz tudo bem” é exagero
      Quando os dados crescem, surgem quedas de desempenho e problemas de migração
      No meu caso, o desempenho do particionamento nativo era ruim, então precisei implementar um particionamento customizado
    • O Postgres ainda é ineficiente na implementação de MVCC (copy-on-write)
      Essa escolha traz vários impactos negativos quando a carga aumenta
    • Antigamente, o MySQL/InnoDB era melhor para workloads centrados em updates
      É um tema tratado também neste post do blog da Uber
      Mesmo assim, no ambiente de nuvem ainda confio mais no Postgres
    • O Postgres ainda não tem uma alternativa com maturidade no nível do Vitess
      Por isso, em implantações OLTP de grande escala, o MySQL continua sendo o mais usado (ex.: YouTube, Uber)
  • Usando estruturas de dados imutáveis (HAMT), dá para criar um DB com clonagem instantânea independentemente do tipo de filesystem
    Eu disse isso em teoria, mas também já implementei na prática
    Não entendo por que não existem mais DBs baseados em HAMT

    • Sou o autor do ClickHouse, e o ClickHouse também usa partes de dados imutáveis para oferecer clonagem de tabelas
      Link para a documentação relacionada
    • Fico curioso se o Datomic também tem esse tipo de clonagem embutida. Tenho vontade de usar há tempos, mas ainda não me sinto pronto para construir um app real com ele
  • Eu não sabia que no Postgres v15 o WAL_LOG passou a ser o padrão
    Em ambientes de teste paralelos no CI, faz mais sentido voltar para a estratégia FILE_COPY
    Abri uma issue sobre isso no antigo projeto integresql

  • Já criei uma ferramenta simples com GUI, pgtt, para testar apps baseados em Postgres localmente
    Ela simplifica bastante a configuração do ambiente de desenvolvimento

    • Só pela README não ficou muito claro, mas fiquei curioso se a estrutura trata templates como snapshots
      Parece que ajudaria no trabalho repetitivo com migrações SQL
    • Seria bom ter uma captura de tela da GUI na README, e o link do Docker está quebrado
  • Li outros posts do blog e, no geral, são excelentes
    Em especial, foi a primeira vez que descobri os tipos range do Postgres

    • Os tipos range são realmente muito úteis para coisas como cálculo de sobreposição de intervalos de tempo/data
  • Fico curioso se o MariaDB também tem algo assim
    Estou quebrando a cabeça porque resetar o DB ao estado inicial a cada teste é lento
    Como usamos MariaDB em produção, é difícil trocar de DB
    Mesmo assim, o lado do Postgres parece melhor

    • Dá para executar cada teste dentro de uma sessão transacional e fazer rollback no fim para restaurar rapidamente o estado inicial
      Esse método é bem eficiente
    • Se reiniciar o DB não for um problema, outra opção é usar snapshots de LVM ou btrfs no nível do filesystem
  • A AWS também oferece um recurso parecido
    Documentação de clones do Aurora

    • Os clones do Aurora funcionam com copy-on-write no nível de storage, mas ainda exigem provisionar um novo cluster, então levam cerca de 10 minutos
      Para testes de integração, isso é pouco prático
    • No Aurora, a clonagem é em nível de cluster, enquanto aqui a discussão é sobre clonagem em nível de banco de dados