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 = 1A 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 = 1Desbloquear 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 VerticalRow 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: 0system.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_partsPara 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. |