メインコンテンツまでスキップ
メインコンテンツまでスキップ

バックアップと復元

コマンドの概要

 BACKUP|RESTORE
  TABLE [db.]table_name [AS [db.]table_name_in_backup]
    [PARTITION[S] partition_expr [,...]] |
  DICTIONARY [db.]dictionary_name [AS [db.]name_in_backup] |
  DATABASE database_name [AS database_name_in_backup]
    [EXCEPT TABLES ...] |
  TEMPORARY TABLE table_name [AS table_name_in_backup] |
  VIEW view_name [AS view_name_in_backup] |
  ALL [EXCEPT {TABLES|DATABASES}...] } [,...]
  [ON CLUSTER 'cluster_name']
  TO|FROM File('<path>/<filename>') | Disk('<disk_name>', '<path>/') | S3('<S3 endpoint>/<path>', '<Access key ID>', '<Secret access key>')
  [SETTINGS base_backup = File('<path>/<filename>') | Disk(...) | S3('<S3 endpoint>/<path>', '<Access key ID>', '<Secret access key>')]

ALL

ClickHouseのバージョン23.4以前では、ALLRESTOREコマンドにのみ適用されました。

背景

レプリケーションはハードウェア障害から保護しますが、人為的なエラー(データの誤削除、間違ったテーブルの削除、間違ったクラスターのテーブル削除、データ処理やデータ破損を引き起こすソフトウェアのバグ)からは保護しません。これらのような間違いは、多くの場合、すべてのレプリカに影響を及ぼします。ClickHouseには、MergeTreeのようなエンジンを使用しているテーブルを単純に削除できないようにするなど、一部のタイプのエラーを防ぐための組み込みの安全策があります。しかし、これらの安全策はすべての可能なケースをカバーしているわけではなく、回避することも可能です。

人為的なエラーを効果的に軽減するためには、事前にデータのバックアップと復元の戦略を慎重に準備する必要があります。

各企業には異なるリソースやビジネス要件があり、すべての状況に適合するClickHouseのバックアップと復元の普遍的な解決策は存在しません。1ギガバイトのデータに対して有効な方法が、数十ペタバイトに対してはうまく機能しない可能性があります。さまざまな利点と欠点を持つ複数のアプローチがありますが、これらについては下で説明します。さまざまな欠点を補うために、「単一のアプローチ」を使用するのではなく、複数のアプローチを使用することをお勧めします。

注記

バックアップを行い、その後復元を試みていない場合、実際に必要なときに復元が正常に動作しない可能性が高いです(または少なくとも業務が許容できるよりも時間がかかります)。したがって、どのバックアップアプローチを選択しても、復元プロセスも自動化し、定期的に予備のClickHouseクラスターで実践することを確認してください。

ローカルディスクへのバックアップ

バックアップ先の設定

以下の例では、バックアップ先がDisk('backups', '1.zip')のように指定されています。バックアップ先を準備するには、/etc/clickhouse-server/config.d/backup_disk.xmlにファイルを追加してバックアップ先を指定します。たとえば、このファイルはbackupsという名前のディスクを定義し、その後そのディスクをbackups > allowed_diskリストに追加します。

<clickhouse>
    <storage_configuration>
        <disks>
<!--highlight-next-line -->
            <backups>
                <type>local</type>
                <path>/backups/</path>
            </backups>
        </disks>
    </storage_configuration>
<!--highlight-start -->
    <backups>
        <allowed_disk>backups</allowed_disk>
        <allowed_path>/backups/</allowed_path>
    </backups>
<!--highlight-end -->
</clickhouse>

パラメータ

バックアップはフルバックアップまたは増分バックアップとすることができ、テーブル(マテリアライズドビュー、プロジェクション、辞書を含む)およびデータベースを含むことができます。バックアップは同期(デフォルト)または非同期であり、圧縮することもできます。バックアップはパスワードで保護することができます。

BACKUPおよびRESTOREステートメントは、DATABASEおよびTABLEの名前のリスト、宛先(またはソース)、オプション、設定を受け取ります:

  • バックアップの宛先、または復元のためのソース。これは前に定義されたディスクに基づいています。たとえばDisk('backups', 'filename.zip')
  • ASYNC: 非同期でバックアップまたは復元する
  • PARTITIONS: 復元するパーティションのリスト
  • SETTINGS:
    • id: バックアップまたは復元操作のID、手動で指定されない場合はランダム生成されたUUIDが使用されます。同じidで実行中の操作がある場合は例外がスローされます。
    • compression_methodとcompression_level
    • ディスク上のファイル用のpassword
    • base_backup: このソースの以前のバックアップの宛先。たとえば、Disk('backups', '1.zip')
    • use_same_s3_credentials_for_base_backup: S3への基本バックアップがクエリから資格情報を継承するかどうか。S3でのみ機能します。
    • use_same_password_for_base_backup: 基本バックアップアーカイブがクエリからパスワードを継承するかどうか。
    • structure_only: 有効にすると、テーブルのデータなしでCREATEステートメントのみをバックアップまたは復元できます。
    • storage_policy: 復元されるテーブルのストレージポリシー。複数のブロックデバイスをデータストレージに使用するを参照してください。この設定はRESTOREコマンドにのみ適用されます。指定されたストレージポリシーは、MergeTreeファミリーのエンジンを持つテーブルにのみ適用されます。
    • s3_storage_class: S3バックアップに使用されるストレージクラス。たとえば、STANDARD
    • azure_attempt_to_create_container: Azure Blob Storageを使用する場合、指定されたコンテナが存在しない場合に作成を試みるかどうか。デフォルト: true。
    • コア設定も使用できます。

使用例

テーブルをバックアップしてから復元します:

BACKUP TABLE test.table TO Disk('backups', '1.zip')

対応する復元:

RESTORE TABLE test.table FROM Disk('backups', '1.zip')
注記

上記のRESTOREはtest.tableがデータを含む場合に失敗します。RESTOREをテストするにはテーブルを削除する必要があるか、allow_non_empty_tables=trueを使用する必要があります:

RESTORE TABLE test.table FROM Disk('backups', '1.zip')
SETTINGS allow_non_empty_tables=true

テーブルは新しい名前で復元またはバックアップできます:

RESTORE TABLE test.table AS test.table2 FROM Disk('backups', '1.zip')
BACKUP TABLE test.table3 AS test.table4 TO Disk('backups', '2.zip')

増分バックアップ

増分バックアップは、base_backupを指定することで取得できます。

注記

増分バックアップは基本バックアップに依存します。増分バックアップから復元するためには基本バックアップを保持しておく必要があります。

新しいデータを増分で保存します。base_backupの設定により、前のバックアップからDisk('backups', 'd.zip')にあるデータがDisk('backups', 'incremental-a.zip')に保存されます:

BACKUP TABLE test.table TO Disk('backups', 'incremental-a.zip')
  SETTINGS base_backup = Disk('backups', 'd.zip')

増分バックアップと基本バックアップからすべてのデータを新しいテーブルtest.table2に復元します:

RESTORE TABLE test.table AS test.table2
  FROM Disk('backups', 'incremental-a.zip');

バックアップにパスワードを割り当てる

ディスクに書き込まれたバックアップには、ファイルにパスワードを設定できます:

BACKUP TABLE test.table
  TO Disk('backups', 'password-protected.zip')
  SETTINGS password='qwerty'

復元:

RESTORE TABLE test.table
  FROM Disk('backups', 'password-protected.zip')
  SETTINGS password='qwerty'

圧縮設定

圧縮方法やレベルを指定したい場合:

BACKUP TABLE test.table
  TO Disk('backups', 'filename.zip')
  SETTINGS compression_method='lzma', compression_level=3

特定のパーティションを復元する

特定のテーブルに関連するパーティションを復元する必要がある場合、これを指定できます。バックアップからパーティション1と4を復元するため:

RESTORE TABLE test.table PARTITIONS '2', '3'
  FROM Disk('backups', 'filename.zip')

tarアーカイブとしてのバックアップ

バックアップはtarアーカイブとして保存することもできます。機能はzipと同じですが、パスワードはサポートされていません。

tarとしてバックアップを書き込む:

BACKUP TABLE test.table TO Disk('backups', '1.tar')

対応する復元:

RESTORE TABLE test.table FROM Disk('backups', '1.tar')

圧縮方法を変更するには、バックアップ名に正しいファイルサフィックスを追加する必要があります。つまり、gzipを使用してtarアーカイブを圧縮するには:

BACKUP TABLE test.table TO Disk('backups', '1.tar.gz')

サポートされている圧縮ファイルのサフィックスはtar.gz.tgztar.bz2tar.lzma.tar.zst.tzst、および.tar.xzです。

バックアップのステータスを確認する

バックアップコマンドはidstatusを返し、そのidを使用してバックアップのステータスを取得できます。これは、長時間の非同期バックアップの進捗を確認するのに非常に便利です。以下の例は、既存のバックアップファイルを上書きしようとしたときに発生した失敗を示しています:

BACKUP TABLE helloworld.my_first_table TO Disk('backups', '1.zip') ASYNC
┌─id───────────────────────────────────┬─status──────────┐
│ 7678b0b3-f519-4e6e-811f-5a0781a4eb52 │ CREATING_BACKUP │
└──────────────────────────────────────┴─────────────────┘

1行がセットにあります。経過時間: 0.001秒。
SELECT
    *
FROM system.backups
where id='7678b0b3-f519-4e6e-811f-5a0781a4eb52'
FORMAT Vertical
Row 1:
──────
id:                7678b0b3-f519-4e6e-811f-5a0781a4eb52
name:              Disk('backups', '1.zip')
#highlight-next-line
status:            BACKUP_FAILED
num_files:         0
uncompressed_size: 0
compressed_size:   0
#highlight-next-line
error:             Code: 598. DB::Exception: Backup Disk('backups', '1.zip') already exists. (BACKUP_ALREADY_EXISTS) (version 22.8.2.11 (official build))
start_time:        2022-08-30 09:21:46
end_time:          2022-08-30 09:21:46

1行がセットにあります。経過時間: 0.002秒。

system.backupsテーブルに加えて、すべてのバックアップおよび復元操作は、システムログテーブルbackup_logにも記録されます:

SELECT *
FROM system.backup_log
WHERE id = '7678b0b3-f519-4e6e-811f-5a0781a4eb52'
ORDER BY event_time_microseconds ASC
FORMAT Vertical
Row 1:
──────
event_date:              2023-08-18
event_time_microseconds: 2023-08-18 11:13:43.097414
id:                      7678b0b3-f519-4e6e-811f-5a0781a4eb52
name:                    Disk('backups', '1.zip')
status:                  CREATING_BACKUP
error:
start_time:              2023-08-18 11:13:43
end_time:                1970-01-01 03:00:00
num_files:               0
total_size:              0
num_entries:             0
uncompressed_size:       0
compressed_size:         0
files_read:              0
bytes_read:              0

Row 2:
──────
event_date:              2023-08-18
event_time_microseconds: 2023-08-18 11:13:43.174782
id:                      7678b0b3-f519-4e6e-811f-5a0781a4eb52
name:                    Disk('backups', '1.zip')
status:                  BACKUP_FAILED
#highlight-next-line
error:                   Code: 598. DB::Exception: Backup Disk('backups', '1.zip') already exists. (BACKUP_ALREADY_EXISTS) (version 23.8.1.1)
start_time:              2023-08-18 11:13:43
end_time:                2023-08-18 11:13:43
num_files:               0
total_size:              0
num_entries:             0
uncompressed_size:       0
compressed_size:         0
files_read:              0
bytes_read:              0

2行がセットにあります。経過時間: 0.075秒。

S3エンドポイントを使用するBACKUP/RESTOREの設定

S3バケットにバックアップを書くには、次の3つの情報が必要です:

  • S3エンドポイント、 例:https://mars-doc-test.s3.amazonaws.com/backup-S3/
  • アクセスキーID、 例:ABC123
  • シークレットアクセスキー、 例:Abc+123
注記

S3バケットの作成については、ClickHouseディスクとしてS3オブジェクトストレージを使用するを参照してください。ポリシーを保存した後はこの文書に戻りますが、ClickHouseをS3バケットで使用するように設定する必要はありません。

バックアップの宛先は以下のように指定されます:

S3('<S3 endpoint>/<directory>', '<Access key ID>', '<Secret access key>')
CREATE TABLE data
(
    `key` Int,
    `value` String,
    `array` Array(String)
)
ENGINE = MergeTree
ORDER BY tuple()
INSERT INTO data SELECT *
FROM generateRandom('key Int, value String, array Array(String)')
LIMIT 1000

基本(初期)バックアップを作成

増分バックアップを取得するには_基本_バックアップから始める必要があります。この例は後で基本バックアップとして使用します。S3の宛先の最初のパラメータはS3エンドポイントで、その後のパラメータはこのバックアップに使用するバケット内のディレクトリです。この例のディレクトリ名はmy_backupです。

BACKUP TABLE data TO S3('https://mars-doc-test.s3.amazonaws.com/backup-S3/my_backup', 'ABC123', 'Abc+123')
┌─id───────────────────────────────────┬─status─────────┐
│ de442b75-a66c-4a3c-a193-f76f278c70f3 │ BACKUP_CREATED │
└──────────────────────────────────────┴────────────────┘

データを追加

増分バックアップは、基本バックアップと現在のテーブルのコンテンツとの違いによって構成されます。増分バックアップを取得する前により多くのデータを追加します:

INSERT INTO data SELECT *
FROM generateRandom('key Int, value String, array Array(String)')
LIMIT 100

増分バックアップを取得

このバックアップコマンドは基本バックアップと似ていますが、SETTINGS base_backupと基本バックアップの場所が追加されます。増分バックアップの宛先は基本バックアップと同じディレクトリではなく、バケット内の異なるターゲットディレクトリです。基本バックアップはmy_backupにあり、増分バックアップはmy_incrementalに書き込まれます:

BACKUP TABLE data TO S3('https://mars-doc-test.s3.amazonaws.com/backup-S3/my_incremental', 'ABC123', 'Abc+123') SETTINGS base_backup = S3('https://mars-doc-test.s3.amazonaws.com/backup-S3/my_backup', 'ABC123', 'Abc+123')
┌─id───────────────────────────────────┬─status─────────┐
│ f6cd3900-850f-41c9-94f1-0c4df33ea528 │ BACKUP_CREATED │
└──────────────────────────────────────┴────────────────┘

増分バックアップから復元

このコマンドは増分バックアップを新しいテーブルdata3に復元します。増分バックアップが復元されると、基本バックアップも含まれることに注意してください。復元する際には増分バックアップのみを指定します:

RESTORE TABLE data AS data3 FROM S3('https://mars-doc-test.s3.amazonaws.com/backup-S3/my_incremental', 'ABC123', 'Abc+123')
┌─id───────────────────────────────────┬─status───┐
│ ff0c8c39-7dff-4324-a241-000796de11ca │ RESTORED │
└──────────────────────────────────────┴──────────┘

行数を確認

元のテーブルdataには、1,000行のインサートと100行のインサートの2つのインサートがあり、合計で1,100行です。復元されたテーブルに1,100行があることを確認します:

SELECT count()
FROM data3
┌─count()─┐
│    1100 │
└─────────┘

コンテンツを確認

元のテーブルdataと復元されたテーブルdata3の内容を比較します:

SELECT throwIf((
        SELECT groupArray(tuple(*))
        FROM data
    ) != (
        SELECT groupArray(tuple(*))
        FROM data3
    ), 'データはバックアップ/復元後に一致しません')

S3ディスクを使用したBACKUP/RESTORE

ClickHouseストレージ構成でS3ディスクを設定することにより、BACKUP/RESTOREをS3に行うことも可能です。このようにディスクを設定します。/etc/clickhouse-server/config.dにファイルを追加します。

<clickhouse>
    <storage_configuration>
        <disks>
            <s3_plain>
                <type>s3_plain</type>
                <endpoint></endpoint>
                <access_key_id></access_key_id>
                <secret_access_key></secret_access_key>
            </s3_plain>
        </disks>
        <policies>
            <s3>
                <volumes>
                    <main>
                        <disk>s3_plain</disk>
                    </main>
                </volumes>
            </s3>
        </policies>
    </storage_configuration>

    <backups>
        <allowed_disk>s3_plain</allowed_disk>
    </backups>
</clickhouse>

その後、通常通りBACKUP/RESTOREを実行します:

BACKUP TABLE data TO Disk('s3_plain', 'cloud_backup');
RESTORE TABLE data AS data_restored FROM Disk('s3_plain', 'cloud_backup');
注記

ただし、次のことを考慮してください:

  • このディスクは、MergeTree自体には使用しないでください。BACKUP/RESTOREのみに使用します。
  • テーブルがS3ストレージにバックアップされ、ディスクのタイプが異なる場合、CopyObject呼び出しを使用してパーツを宛先バケットにコピーせず、代わりにダウンロードしてアップロードすることになります。これは非常に非効率的です。このユースケースでは、BACKUP ... TO S3(<endpoint>)構文を使用することをお勧めします。

名前付きコレクションの使用

名前付きコレクションは、BACKUP/RESTOREパラメータに使用できます。こちらで例を参照してください。

代替手段

ClickHouseはディスク上にデータを保存しており、ディスクのバックアップには多くの方法があります。これまでに使用された代替手段の一部は、環境に適合する可能性があります。

ソースデータを他の場所に複製

ClickHouseに取り込まれるデータは、Apache Kafkaなどの持続的キューを介して提供されることが多いです。この場合、データがClickHouseに書き込まれている間に、同じデータストリームを読み取る追加のサブスクライバーを設定し、別の冷ストレージに保存することが可能です。ほとんどの企業には、オブジェクトストレージやHDFSのような分散ファイルシステムなど、デフォルトで推奨される冷ストレージがあります。

ファイルシステムスナップショット

一部のローカルファイルシステムはスナップショット機能を提供しています(たとえば、ZFS)。ただし、これらはライブクエリに最適ではないかもしれません。可能な解決策は、この種のファイルシステムを持つ追加のレプリカを作成し、SELECTクエリで使用されるDistributedテーブルから除外することです。そのようなレプリカのスナップショットは、データを変更するクエリのリーチから外れます。ボーナスとして、これらのレプリカは、サーバーごとにより多くのディスクが接続された特別なハードウェア構成を持つ可能性があり、コスト効率が良いです。

データのボリュームが小さい場合は、単純なINSERT INTO ... SELECT ...をリモートテーブルに使用することも可能です。

パーツの操作

ClickHouseは、ALTER TABLE ... FREEZE PARTITION ...クエリを使用して、テーブルパーティションのローカルコピーを作成することを許可します。これは、/var/lib/clickhouse/shadow/フォルダーへのハードリンクを使用して実装されるため、通常は古いデータの余分なディスクスペースを消費しません。ファイルの作成されたコピーはClickHouseサーバーによって処理されないため、そのままにしておくことができます: これにより、追加の外部システムを必要としない簡単なバックアップが得られますが、それでもハードウェアの問題には弱いです。そのため、リモートで別の場所にコピーしてから、ローカルコピーを削除するのが良いでしょう。分散ファイルシステムやオブジェクトストレージはまだ良い選択肢ですが、十分な容量を持つ通常の接続ファイルサーバーでも機能することがあります(この場合、転送はネットワークファイルシステムまたはrsyncを介して行われます)。 バックアップからデータを復元するにはALTER TABLE ... ATTACH PARTITION ...を使用します。

パーティション操作に関連するクエリについての詳細は、ALTERドキュメントを参照してください。

このアプローチを自動化するためのサードパーティツールがあります:clickhouse-backup

同時バックアップ/復元を禁止する設定

同時バックアップ/復元を禁止するには、それぞれ次の設定を使用できます。

<clickhouse>
    <backups>
        <allow_concurrent_backups>false</allow_concurrent_backups>
        <allow_concurrent_restores>false</allow_concurrent_restores>
    </backups>
</clickhouse>

どちらもデフォルトではtrueであるため、デフォルトでは同時バックアップ/復元が許可されています。 これらの設定がクラスターでfalseのとき、同時に実行できるバックアップ/復元は1つのみです。

AzureBlobStorageエンドポイントを使用するBACKUP/RESTOREの設定

AzureBlobStorageコンテナにバックアップを書くには、次の情報が必要です:

  • AzureBlobStorageエンドポイント接続文字列/ URL、
  • コンテナ、
  • パス、
  • アカウント名(URLが指定される場合)
  • アカウントキー(URLが指定される場合)

バックアップの宛先は以下のように指定されます:

AzureBlobStorage('<connection string>/<url>', '<container>', '<path>', '<account name>', '<account key>')
BACKUP TABLE data TO AzureBlobStorage('DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://azurite1:10000/devstoreaccount1/;',
    'testcontainer', 'data_backup');
RESTORE TABLE data AS data_restored FROM AzureBlobStorage('DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://azurite1:10000/devstoreaccount1/;',
    'testcontainer', 'data_backup');

システムテーブルのバックアップ

システムテーブルもバックアップおよび復元ワークフローに含めることができますが、その含有は特定のユースケースによって異なります。

ログテーブルのバックアップ

履歴データを保存するシステムテーブル(query_logpart_logのように_ログの接尾辞を持つテーブル)は、他のテーブルと同様にバックアップおよび復元できます。ユースケースが履歴データの分析に依存している場合(たとえば、クエリ性能を追跡するためにquery_logを使用するなど)、これらのテーブルをバックアップ戦略に含めることをお勧めします。ただし、これらのテーブルからの履歴データが必要ない場合、バックアップストレージスペースを節約するために除外することができます。

アクセス管理テーブルのバックアップ

ユーザー、ロール、行ポリシー、設定プロファイル、クォータなどのアクセス管理に関連するシステムテーブルは、バックアップおよび復元操作中に特別扱いされます。これらのテーブルがバックアップに含まれると、その内容は特別なaccessXX.txtファイルにエクスポートされ、アクセスエンティティを作成および設定するための等価のSQLステートメントがカプセル化されます。復元時には、復元プロセスがこれらのファイルを解釈し、SQLコマンドを再適用してユーザー、ロール、および他の設定を再作成します。

この機能により、ClickHouseクラスターのアクセス制御構成をバックアップおよび復元することができ、クラスター全体のセットアップの一部として利用できます。

注意:この機能は、SQLコマンドを介して管理される構成に対してのみ機能します(「SQL駆動のアクセス制御とアカウント管理」を参照)。ClickHouseサーバー構成ファイル(例:users.xml)で定義されたアクセス構成はバックアップに含まれず、この方法で復元することはできません。