This section broadly covers backups and restores in ClickHouse. For a more detailed description of each backup method, see the pages for specific methods in the sidebar.
Introduction
While replication provides protection from hardware failures, it doesn’t protect against human errors: accidental deletion of data, deletion of the wrong table or a table on the wrong cluster, and software bugs that result in incorrect data processing or data corruption. In many cases mistakes like these will affect all replicas. ClickHouse has built-in safeguards to prevent some types of mistakes, for example, by default you can’t just drop tables with aMergeTree family engine containing more than
50 Gb of data. However, these safeguards don’t cover all possible cases and
problems can still occur.
To effectively mitigate possible human errors, you should carefully prepare a
strategy for backing up and restoring your data in advance.
Each company has different resources available and business requirements, so
there’s no universal solution for ClickHouse backups and restores that will fit
every situation. What works for one gigabyte of data likely won’t work for tens
of petabytes of data. There are a variety of possible approaches with their own pros
and cons, which are presented in this section of the docs. It is a good idea to
use several approaches instead of just one such as to compensate for their various
shortcomings.
Keep in mind that if you backed something up and never tried to restore it,
chances are that the restore won’t work properly when you actually need it (or at
least it will take longer than the business can tolerate). So whatever backup
approach you choose, make sure to automate the restore process as well, and practice
it on a spare ClickHouse cluster regularly.
Backups can:
- be full or incremental
- be synchronous or asynchronous
- be concurrent or non-concurrent
- be compressed or uncompressed
- use named collections
- be password protected
- be taken of system tables, log tables, or access management tables
Backup types
Backups can be either full or incremental. Full backups are a complete copy of the data, while incremental backups are a delta of the data from the last full backup. Full backups have the advantage of being a simple, independent (of other backups) and reliable recovery method. However, they can take a long time to complete and can consume a lot of space. Incremental backups, on the other hand, are more efficient in terms of both time and space, but restoring the data requires all the backups to be available. Depending on your needs, you may want to use:- Full backups for smaller databases or critical data.
- Incremental backups for larger databases or when backups need to be done frequently and cost effectively.
- Both, for instance, weekly full backups and daily incremental backups.
Synchronous vs asynchronous backups
BACKUP and RESTORE commands can also be marked ASYNC. In this case, the
backup command returns immediately, and the backup process runs in the background.
If the commands aren’t marked ASYNC, the backup process is synchronous and
the command blocks until the backup completes.
Concurrent vs non-concurrent backups
By default, ClickHouse allows concurrent backups and restores. This means you can initiate multiple backup or restore operations simultaneously. However, there are server-level settings that let you disallow this behavior. If you set these settings to false, only one backup or restore operation is allowed to run on a cluster at a time. This can help avoid resource contention or potential conflicts between operations. To disallow concurrent backup/restore, you can use these settings respectively:Compressed vs uncompressed backups
ClickHouse backups support compression through thecompression_method and compression_level settings.
When creating a backup, you can specify:
Using named collections
Named collections allow you to store key-value pairs (like S3 credentials, endpoints, and settings) that can be reused across backup/restore operations. They help to:- Hide credentials from users without admin access
- Simplify commands by storing complex configuration centrally
- Maintain consistency across operations
- Avoid credential exposure in query logs
Backing up system, log or access management tables
System tables can also be included in your backup and restore workflows, but their inclusion depends on your specific use case. System tables that store historic data, such as those with a_log suffix (e.g.,
query_log, part_log), can be backed up and restored like any other table.
If your use case relies on analyzing historic data - for example, using query_log
to track query performance or debug issues - it’s recommended to include these
tables in your backup strategy. However, if historic data from these tables is
not required, they can be excluded to save backup storage space.
System tables related to access management, such as users, roles, row_policies,
settings_profiles, and quotas, receive special treatment during backup and restore operations.
When these tables are included in a backup, their content is exported to a special
accessXX.txt file, which encapsulates the equivalent SQL statements for creating
and configuring the access entities. Upon restoration, the restore process
interprets these files and re-applies the SQL commands to recreate the users,
roles, and other configurations. This feature ensures that the access control
configuration of a ClickHouse cluster can be backed up and restored as part of
the cluster’s overall setup.
This functionality only works for configurations managed through SQL commands
(referred to as “SQL-driven Access Control and Account Management”).
Access configurations defined in ClickHouse server configuration files (e.g. users.xml)
aren’t included in backups and can’t be restored through this method.
General syntax
Command summary
Each of the commands above is detailed below:Backing up a table without its data
EXCEPT DATA FROM {TABLE|TABLES} puts a table’s definition in the backup without its rows. It is useful
for tables whose contents can be regenerated after a restore, for example the target tables of materialized
views.
The clause decides what BACKUP writes; it does not change what RESTORE is able to do with the result. For
a table that RESTORE can recreate, a definition without rows restores as an empty table. It does not make a
table restorable that would not be restorable anyway - whether a definition in the backup can be turned back
into a table is up to the engine, and some engines refuse it outright: see
Engines that RESTORE cannot recreate.
The clause is scoped to the element it is written on:
- On a
DATABASEorALLelement it may name any table that element backs up:
- On a single-object element (
TABLE,DICTIONARY,VIEW,TEMPORARY TABLE) the element’s own object is the only one in scope, so the clause must name it and nothing else. Give every table its own element and its own clause:
EXCEPT DATA FROM clause of a wider element,
its data is backed up: an element asking for a table asks for its data. This matches EXCEPT TABLES,
where a table named explicitly is backed up even though a wider element excludes it.
The data of the inner table of a materialized view (or of the inner tables of a TimeSeries table) is
excluded through the outer object’s name; inner table names are not accepted by the clause.
EXCEPT DATA FROM {TABLE|TABLES} is only valid for BACKUP. RESTORE rejects it, rather than accepting it
as a no-op.
Engines that RESTORE cannot recreate
A few engines cannot be recreated by RESTORE at all, with or without EXCEPT DATA FROM {TABLE|TABLES}. For
those tables the clause still controls the size of the backup, but it does not give you a table that comes
back empty - nothing comes back in place, because RESTORE refuses to create the table.
A standalone MaterializedPostgreSQL table is the case to know about. It would start replicating from the
live PostgreSQL source as soon as it was created, mixing the backup snapshot with the current remote state, so
RESTORE rejects it in the storage factory - before the table is created - with NOT_IMPLEMENTED. This is a
property of the engine and applies to an ordinary full backup just the same.
The supported flow is to restore under a different name, into a ReplacingMergeTree that you created
beforehand with the structure of the nested table (including the _sign and _version columns):
allow_different_table_def is required because the definition stored in the backup uses the
MaterializedPostgreSQL engine, which is deliberately being restored into a plain ReplacingMergeTree.
Without EXCEPT DATA FROM TABLE the same RESTORE brings the rows across instead.
Settings
Generic backup/restore settings
S3 specific settings
Azure specific settings
Administration and troubleshooting
The backup command returns anid and status, and that id can be used to
get the status of the backup. This is very useful to check the progress of long
ASYNC backups. The example below shows a failure that happened when trying to
overwrite an existing backup file:
system.backups table, all backup and restore operations are also tracked in the system log table
system.backup_log: