Skip to content
ClickHouse Docs
ClickHouse DocsClickHouse Docs

Backup e restauração por snapshot

O backup por snapshot é um modo de backup leve para motores de tabela cloud-native. Em vez de copiar os dados, ele grava nós de bloqueio para cada parte no ClickHouse Keeper. Esses bloqueios impedem que o servidor exclua as partes referenciadas no armazenamento de objetos enquanto o snapshot for mantido. Em seguida, o backup registra as referências no armazenamento de objetos, em vez de copiar fisicamente os dados, o que torna a criação de snapshots rápida, independentemente do tamanho da tabela.

O modo leve se aplica às tabelas SharedMergeTree, SharedSet e SharedJoin. Para todos os outros tipos de motor — como Log ou Memory — o backup volta automaticamente para um backup padrão baseado em cópia.

Criar um snapshot

O backup por snapshot usa o comando padrão BACKUP com experimental_lightweight_snapshot = true. A configuração id é obrigatória — ela dá nome ao snapshot e é usada para referenciá-lo nos comandos de desbloqueio e observabilidade:

BACKUP { TABLE [db.]table_name | DATABASE db_name | ALL [EXCEPT {TABLES | DATABASES} ...] }
TO { S3(...) | AzureBlobStorage(...) }
SETTINGS experimental_lightweight_snapshot = true, id = '<snapshot_id>'

O comando retorna o id e o status, e o id pode ser usado para acompanhar a operação em system.backups.

Faça backup de uma única tabela para o S3:

BACKUP TABLE mydb.events
TO S3('https://my-bucket.s3.us-east-1.amazonaws.com/snapshots/events/', 'ACCESS_KEY_ID', 'SECRET_ACCESS_KEY')
SETTINGS experimental_lightweight_snapshot = true, id = 'events_snapshot_1'

Faça backup de um banco de dados completo:

BACKUP DATABASE mydb
TO S3('https://my-bucket.s3.us-east-1.amazonaws.com/snapshots/mydb/', 'ACCESS_KEY_ID', 'SECRET_ACCESS_KEY')
SETTINGS experimental_lightweight_snapshot = true, id = 'mydb_snapshot_1'

Faça backup de todas as tabelas, exceto uma:

BACKUP ALL
EXCEPT TABLES mydb.staging_table
TO S3('https://my-bucket.s3.us-east-1.amazonaws.com/snapshots/full/', 'ACCESS_KEY_ID', 'SECRET_ACCESS_KEY')
SETTINGS experimental_lightweight_snapshot = true, id = 'full_snapshot_1'

Os mesmos comandos também funcionam com o Azure Blob Storage:

BACKUP TABLE mydb.events
TO AzureBlobStorage('DefaultEndpointsProtocol=https;AccountName=myaccount;AccountKey=...', 'my-container', 'snapshots/events/')
SETTINGS experimental_lightweight_snapshot = true, id = 'events_snapshot_1'

Restaurar para o mesmo serviço

Como um snapshot armazena referências a arquivos no armazenamento de objetos, em vez de cópias dos dados, a restauração em um serviço do ClickHouse novo ou diferente exige acesso ao armazenamento de objetos original. Por esse motivo, a restauração entre serviços não tem suporte via SQL — ela só está disponível pela UI. Via SQL, você pode restaurar um snapshot para o mesmo serviço a partir de um bucket de backup externo usando snapshot_from_current_service = 1. Isso lê objetos diretamente pelo disco de destino, em vez de passar por um leitor remoto de snapshot:

RESTORE TABLE mydb.events AS mydb.events_restored
FROM S3('https://my-bucket.s3.us-east-1.amazonaws.com/snapshots/events/', 'ACCESS_KEY_ID', 'SECRET_ACCESS_KEY')
SETTINGS snapshot_from_current_service = 1

A cláusula AS restaura os dados com um novo nome de tabela, mantendo a tabela original intacta. Para sobrescrever a tabela original, exclua-a primeiro:

DROP TABLE mydb.events;

RESTORE TABLE mydb.events
FROM S3('https://my-bucket.s3.us-east-1.amazonaws.com/snapshots/events/', 'ACCESS_KEY_ID', 'SECRET_ACCESS_KEY')
SETTINGS snapshot_from_current_service = 1

Desbloquear um snapshot

Cada snapshot mantém bloqueios no ClickHouse Keeper que impedem que os arquivos referenciados no armazenamento de objetos sejam removidos pela coleta de lixo. Após a conclusão de uma restauração — ou quando um snapshot não for mais necessário — desbloqueie-o para liberar esses bloqueios.

Há duas formas: um desbloqueio em nível de sistema, que remove todos os bloqueios do snapshot de uma só vez, e um desbloqueio por tabela, que remove o bloqueio de uma única tabela e mantém o restante do snapshot intacto.

Desbloqueio em nível de sistema — remove todos os bloqueios do snapshot:

SYSTEM UNLOCK SNAPSHOT '<snapshot_id>'
FROM S3('https://my-bucket.s3.us-east-1.amazonaws.com/snapshots/events/', 'ACCESS_KEY_ID', 'SECRET_ACCESS_KEY')

Desbloqueio por tabela — remove o bloqueio de apenas uma tabela:

ALTER TABLE mydb.events UNLOCK SNAPSHOT '<snapshot_id>'
FROM S3('https://my-bucket.s3.us-east-1.amazonaws.com/snapshots/events/', 'ACCESS_KEY_ID', 'SECRET_ACCESS_KEY')

A cláusula FROM é opcional quando o destino do snapshot foi armazenado no Keeper no momento da criação (visível na coluna info de system.snapshot_locks):

SYSTEM UNLOCK SNAPSHOT '<snapshot_id>'

-- ou por tabela:
ALTER TABLE mydb.events UNLOCK SNAPSHOT '<snapshot_id>'

Após o desbloqueio, a linha correspondente desaparece de system.snapshot_locks, e as partes que não são mais referenciadas por outros snapshots deixam de constar em system.snapshot_parts.

Observabilidade

system.backups

Todas as operações de snapshot aparecem em system.backups, junto com as operações regulares de backup e restauração. Consulte essa tabela usando o id que você definiu (ou o UUID retornado pelo comando):

SELECT id, name, status, error, start_time, end_time, num_files, uncompressed_size, compressed_size
FROM system.backups
WHERE id = 'events_snapshot_1'
FORMAT Vertical
Row 1:
──────
id:                events_snapshot_1
name:              S3('https://my-bucket.s3.us-east-1.amazonaws.com/snapshots/events/', '[HIDDEN]')
status:            BACKUP_CREATED
error:
start_time:        2024-06-01 10:00:00
end_time:          2024-06-01 10:00:03
num_files:         42
uncompressed_size: 1073741824
compressed_size:   0

system.snapshot_locks

system.snapshot_locks mostra os snapshots confirmados atualmente registrados no Keeper. Quando um snapshot é confirmado, um nó no Keeper é criado em /clickhouse/snapshot/committed/{snapshot_id}. Antes de excluir qualquer parte de dados, o servidor verifica se algum snapshot confirmado mantém um bloqueio sobre essa parte de dados. Se mantiver, a exclusão não é realizada. O bloqueio persiste até que você desbloqueie o snapshot explicitamente.

SELECT *
FROM system.snapshot_locks
Coluna Tipo Descrição
id String ID do snapshot
info String Destino do snapshot, por exemplo S3('...')
ctime DateTime Quando este bloqueio foi criado no Keeper
lock_path String Caminho no Keeper para este bloqueio

Cada linha representa um snapshot concluído. Se você vir bloqueios de snapshots que não têm mais um destino de backup válido, execute SYSTEM UNLOCK SNAPSHOT para removê-los.

Para verificar se existe um bloqueio para um snapshot específico:

SELECT id, info, lock_path
FROM system.snapshot_locks
WHERE id = 'events_snapshot_1'

system.snapshot_parts

system.snapshot_parts mostra as partes de dados atualmente retidas por pelo menos um bloqueio de snapshot. Para cada parte bloqueada, existe um nó do Keeper em /clickhouse/snapshot/{table_uuid}/{part_name} contendo o tamanho compactado e o tamanho sem compactação da parte. Esta tabela lê esses nós para mostrar quais partes estão atualmente protegidas contra exclusão.

SELECT *
FROM system.snapshot_parts
ORDER BY data_compressed_bytes DESC
LIMIT 20
Coluna Tipo Descrição
name String Nome da parte de dados
table_id String UUID da tabela à qual esta parte pertence
data_compressed_bytes UInt64 Tamanho compactado desta parte
data_uncompressed_bytes UInt64 Tamanho descompactado desta parte
snapshots_size UInt64 Número de snapshots que atualmente mantêm um bloqueio sobre esta parte

Partes com snapshots_size > 1 são referenciadas por vários snapshots e não serão removidas do armazenamento de objetos até que todos os snapshots que as mantêm sejam liberados.

Para verificar o total de armazenamento retido:

SELECT
    formatReadableSize(sum(data_compressed_bytes)) AS total_pinned_compressed,
    formatReadableSize(sum(data_uncompressed_bytes)) AS total_pinned_uncompressed,
    count() AS parts_count
FROM system.snapshot_parts

Para encontrar partes bloqueadas por um snapshot, mas que já foram removidas ou não estão mais ativas no servidor — ou seja, dados mantidos no armazenamento de objetos exclusivamente por causa de bloqueios de snapshot:

SELECT
    count(*),
    sum(data_uncompressed_bytes)
FROM system.snapshot_parts
WHERE (name, table_id) NOT IN (
    SELECT
        name,
        toString(tables.uuid)
    FROM system.parts
    INNER JOIN system.tables ON (parts.`table` = tables.name) AND parts.active
)
┌─count()─┬─sum(data_uncompressed_bytes)─┐
│    1000 │                        96037 │
└─────────┴──────────────────────────────┘

Isso é útil para entender o overhead de armazenamento de manter snapshots depois que os dados originais foram alterados ou removidos.

Configurações do servidor

Os parâmetros a seguir da configuração do servidor controlam o comportamento dos snapshots. Eles são definidos no arquivo de configuração do servidor, não em SQL.

Configuração Tipo Padrão Pode ser alterado sem reiniciar Descrição
max_held_snapshots UInt64 0 Não Número máximo de snapshots leves que podem ser mantidos ao mesmo tempo. 0 significa ilimitado. Se o limite for atingido, a criação de um novo snapshot lança uma exceção.
max_snapshot_commit_thread_pool_size UInt64 64 Sim Número de threads usadas para confirmar nós de bloqueio de snapshot no Keeper. Aumente esse valor se a criação de snapshots estiver lenta em tabelas grandes com muitas partes.
max_snapshot_commit_thread_pool_free_size UInt64 0 Sim Se o número de threads ociosas no pool de confirmação de snapshots exceder esse valor, o ClickHouse libera essas threads e reduz o pool. As threads são criadas novamente sob demanda. 0 significa que threads ociosas nunca são liberadas.
snapshot_cleaner_period UInt64 120 Não Com que frequência (em segundos) o limpador de snapshots é executado para remover partes que não são mais referenciadas por nenhum bloqueio de snapshot. Somente no ClickHouse Cloud.
snapshot_cleaner_pool_size UInt64 128 Não Número de threads no pool de threads do limpador de snapshots. Somente no ClickHouse Cloud.
Navigation