スナップショットバックアップは、クラウドネイティブなテーブルエンジン向けの軽量バックアップモードです。データをコピーする代わりに、ClickHouse Keeper に各パーツのロックノードを書き込みます。これらのロックにより、スナップショットが保持されている間、server は参照先のオブジェクトストレージ上のパーツを削除できません。バックアップではその後、データを物理的にコピーする代わりにオブジェクトストレージへの参照を記録するため、テーブルサイズに関係なくスナップショットを高速に作成できます。
この軽量方式は、SharedMergeTree、SharedSet、SharedJoin テーブルに適用されます。Log や Memory など、それ以外のすべてのエンジンタイプでは、自動的に標準のコピー方式バックアップにフォールバックします。
スナップショットを作成する
スナップショットバックアップでは、標準の BACKUP コマンドに experimental_lightweight_snapshot = true を指定して使用します。id 設定は必須で、スナップショットに名前を付けるために使われ、ロック解除コマンドやオブザーバビリティコマンドから参照する際にも使用されます。
BACKUP { TABLE [db.]table_name | DATABASE db_name | ALL [EXCEPT {TABLES | DATABASES} ...] }
TO { S3(...) | AzureBlobStorage(...) }
SETTINGS experimental_lightweight_snapshot = true, id = '<snapshot_id>'このコマンドは id と status を返します。id は system.backups で操作の進行状況を追跡するために使用できます。
単一のテーブルを 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'データベース全体をバックアップする:
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'1つを除くすべてのテーブルをバックアップします:
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'同じコマンドは 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'同じサービスに復元する
スナップショットはデータのコピーではなく、オブジェクトストレージ内のファイルへの参照を保存するため、新しい、または別の ClickHouse サービスに復元するには、元のオブジェクトストレージへのアクセスが必要です。そのため、サービス間の復元は SQL ではサポートされておらず、UI からのみ実行できます。SQL では、snapshot_from_current_service = 1 を使用することで、外部バックアップバケットから同じサービスにスナップショットを復元できます。これにより、リモートのスナップショットリーダーを経由せず、宛先ディスク経由でオブジェクトを直接読み取ります:
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 = 1AS 句を使うと、新しいテーブル名で復元され、元のテーブルはそのまま残ります。元のテーブルを上書きするには、まずそのテーブルを削除してください:
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スナップショットのロック解除
各スナップショットは ClickHouse Keeper にロックを保持し、参照先のオブジェクトストレージ内のファイルがガベージコレクションされるのを防ぎます。復元が完了したら、またはスナップショットが不要になったら、それらのロックを解放するためにロック解除を行います。
ロック解除には 2 つの形式があります。1 つはスナップショットに対するすべてのロックを一度に削除するシステムレベルのロック解除、もう 1 つはスナップショットの残りをそのまま維持したまま、単一のテーブルに対するロックだけを削除するテーブル単位のロック解除です。
システムレベルのロック解除 — スナップショットに対するすべてのロックを削除します:
SYSTEM UNLOCK SNAPSHOT '<snapshot_id>'
FROM S3('https://my-bucket.s3.us-east-1.amazonaws.com/snapshots/events/', 'ACCESS_KEY_ID', 'SECRET_ACCESS_KEY')テーブルごとのロック解除 — 1つのテーブルのロックだけを解除します:
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')スナップショットの宛先が作成時に Keeper に保存されている場合 (system.snapshot_locks の info カラムで確認可能) 、FROM 句は省略できます。
SYSTEM UNLOCK SNAPSHOT '<snapshot_id>'
-- またはテーブル単位:
ALTER TABLE mydb.events UNLOCK SNAPSHOT '<snapshot_id>'ロック解除後、対応する行はsystem.snapshot_locksから消え、他のスナップショットから参照されていないパーツはsystem.snapshot_partsからも消えます。
オブザーバビリティ
system.backups
すべてのスナップショット操作は、通常のバックアップおよびリストア操作とともに system.backups に表示されます。設定した id (またはコマンドが返した UUID) を指定してクエリします。
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 には、現在 Keeper に登録されているコミット済みスナップショットが表示されます。スナップショットがコミットされると、/clickhouse/snapshot/committed/{snapshot_id} に Keeper ノードが作成されます。data パーツ を削除する前に、server はコミット済みスナップショットがその パーツ に対するロックを保持しているかどうかを確認します。保持している場合、その削除はスキップされます。このロックは、スナップショットを明示的にロック解除するまで保持されます。
SELECT *
FROM system.snapshot_locks| カラム | 型 | 説明 |
|---|---|---|
id |
String |
スナップショット ID |
info |
String |
スナップショットの保存先 (例: S3('...')) |
ctime |
DateTime |
このロックが Keeper で作成された時刻 |
lock_path |
String |
このロックの Keeper パス |
各行は、コミット済みのスナップショットを 1 つ表します。すでに有効な保存先が存在しないスナップショットのロックが見つかった場合は、SYSTEM UNLOCK SNAPSHOT を実行してクリーンアップしてください。
特定のスナップショットロックが存在するかどうかを確認するには:
SELECT id, info, lock_path
FROM system.snapshot_locks
WHERE id = 'events_snapshot_1'system.snapshot_parts
system.snapshot_parts は、少なくとも 1 つのスナップショットロックによって現在固定されている data パーツ を表示します。ロックされている各 data パーツ については、/clickhouse/snapshot/{table_uuid}/{part_name} に Keeper ノードが存在し、その data パーツ の圧縮サイズと非圧縮サイズが格納されます。このテーブルはそれらのノードを読み取り、現在削除から保護されているパーツを表示します。
SELECT *
FROM system.snapshot_parts
ORDER BY data_compressed_bytes DESC
LIMIT 20| カラム | 型 | 説明 |
|---|---|---|
name |
String |
データパーツ名 |
table_id |
String |
このパーツが属するテーブルの UUID |
data_compressed_bytes |
UInt64 |
このパーツの圧縮サイズ |
data_uncompressed_bytes |
UInt64 |
このパーツの非圧縮サイズ |
snapshots_size |
UInt64 |
現在このパーツをロックしているスナップショットの数 |
snapshots_size > 1 のパーツは複数のスナップショットから参照されており、ロックを保持しているすべてのスナップショットがロック解除されるまで、オブジェクトストレージから削除されません。
ピン留めされているストレージの合計を確認するには:
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スナップショットによってロックされているものの、すでに削除されているか、サーバー上でアクティブでなくなっているパーツ、つまりスナップショットロックのためだけにオブジェクトストレージに保持されているデータを見つけるには:
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 │
└─────────┴──────────────────────────────┘これは、元のデータが変更または削除された後もスナップショットを保持することで発生するストレージのオーバーヘッドを把握するのに役立ちます。
サーバー設定
以下のサーバー設定パラメータは、スナップショットの動作を制御します。これらはSQLではなく、サーバー設定ファイルで設定します。
| 設定 | 型 | デフォルト | 再起動なしで変更可能 | 説明 |
|---|---|---|---|---|
max_held_snapshots |
UInt64 | 0 |
いいえ | 同時に保持できる軽量スナップショットの最大数です。0 は無制限を意味します。上限に達すると、新しいスナップショットを作成しようとしたときに例外がスローされます。 |
max_snapshot_commit_thread_pool_size |
UInt64 | 64 |
はい | スナップショットのロックノードをKeeperにコミットするために使用するスレッド数です。多数のパーツを持つ大規模なテーブルでスナップショットの作成が遅い場合は、この値を増やしてください。 |
max_snapshot_commit_thread_pool_free_size |
UInt64 | 0 |
はい | スナップショットコミットプール内のアイドルスレッド数がこの値を超えると、ClickHouse はそれらのスレッドを解放してプールを縮小します。スレッドは必要に応じて再作成されます。0 は、アイドルスレッドが解放されないことを意味します。 |
snapshot_cleaner_period |
UInt64 | 120 |
いいえ | スナップショットクリーナーが、どのスナップショットロックからも参照されなくなったパーツを削除するために実行される間隔 (秒) です。ClickHouse Cloud のみ。 |
snapshot_cleaner_pool_size |
UInt64 | 128 |
いいえ | スナップショットクリーナーのスレッドプール内のスレッド数です。ClickHouse Cloud のみ。 |