トランザクション (ACID) サポート
ケース 1: MergeTree* ファミリーの1つのテーブルの1つのパーティションにINSERT
これは、挿入された行がパックされ、単一のブロックとして挿入される場合、トランザクショナル (ACID) です (ノートを参照):
- 原子性: INSERT は全体として成功するか、拒否されます。クライアントに確認が送信される場合、すべての行が挿入されたことになります。クライアントにエラーが送信される場合、行は挿入されません。
- 一貫性: テーブルの制約に違反がない場合、INSERT のすべての行が挿入され、INSERT は成功します。制約に違反がある場合、行は挿入されません。
- 独立性: 同時実行のクライアントは、テーブルの一貫したスナップショットを観察します。つまり、INSERT の試行の前のテーブルの状態、または成功した INSERT の後の状態を観察します。部分的な状態は表示されません。他のトランザクション内のクライアントは スナップショット隔離 を持ち、トランザクション外のクライアントは 未コミットの読み取り の隔離レベルを持ちます。
- 耐久性: 成功した INSERT は、クライアントに応答する前にファイルシステムに書き込まれます。単一のレプリカまたは複数のレプリカに書き込まれます (これを制御するのが
insert_quorum
設定) 。ClickHouse は、OS に対してストレージメディアのファイルシステムデータを同期するように依頼できます (これを制御するのがfsync_after_insert
設定)。 - 1つのステートメントで複数のテーブルにINSERTすることも、マテリアライズドビューが関与している場合は可能です (クライアントからのINSERTが関連するマテリアライズドビューを持つテーブルに対して行われます)。
ケース 2: MergeTree* ファミリーの1つのテーブルに複数のパーティションにINSERT
上記のケース 1 と同様ですが、以下の詳細があります:
- テーブルに多数のパーティションがあり、INSERT が多数のパーティションをカバーする場合、すべてのパーティションへの挿入はそれぞれ独立してトランザクショナルです。
ケース 3: MergeTree* ファミリーの1つの分散テーブルにINSERT
上記のケース 1 と同様ですが、以下の詳細があります:
- 分散テーブルへのINSERTは全体としてトランザクショナルではなく、各シャードへの挿入はトランザクショナルです。
ケース 4: バッファテーブルの使用
- バッファテーブルへのINSERTは原子性も独立性も一貫性も耐久性もありません。
ケース 5: async_insert の使用
上記のケース 1 と同様ですが、以下の詳細があります:
async_insert
が有効でwait_for_async_insert
が 1 (デフォルト) に設定されている場合でも原子性が保証されますが、wait_for_async_insert
が 0 に設定されている場合は原子性が保証されません。
ノート
- クライアントから挿入された行は、次の条件を満たす場合に単一のブロックにパックされます:
- 挿入形式が行ベース (CSV、TSV、Values、JSONEachRow など) で、データが
max_insert_block_size
行 (デフォルトで約1,000,000) 未満、または並列パースが使用されている場合 (デフォルトで有効) はmin_chunk_bytes_for_parallel_parsing
バイト (デフォルトで10MB) 未満である場合 - 挿入形式がカラムベース (Native、Parquet、ORC など) で、データがデータのブロックを1つだけ含む場合
- 挿入形式が行ベース (CSV、TSV、Values、JSONEachRow など) で、データが
- 挿入されたブロックのサイズは、一般的に多くの設定 (たとえば:
max_block_size
、max_insert_block_size
、min_insert_block_size_rows
、min_insert_block_size_bytes
、preferred_block_size_bytes
など) に依存することがあります。 - クライアントがサーバーから応答を受け取らなかった場合、クライアントはトランザクションが成功したかどうかを知らず、正確に1回の挿入プロパティを使用してトランザクションを繰り返すことができます。
- ClickHouseは、同時トランザクションのために内部で MVCC と スナップショット隔離 を使用しています。
- すべての ACID プロパティは、サーバーが強制終了/クラッシュした場合でも有効です。
- 一般的なセットアップでは、耐久性のある挿入を確保するために、異なる AZ への insert_quorum または fsync を有効にする必要があります。
- ACID の用語での「一貫性」は、分散システムの意味を網羅していません。詳細は https://jepsen.io/consistency を参照してください。これを制御するのは異なる設定 (select_sequential_consistency) です。
- この説明では、複数のテーブルやマテリアライズドビュー、複数の SELECT に対してフル機能のトランザクションを持つ新しいトランザクション機能については触れません (次の「トランザクション、コミット、ロールバック」のセクションを参照してください)。
トランザクション、コミット、およびロールバック
この文書の最初に記載されている機能に加えて、ClickHouse はトランザクション、コミット、およびロールバック機能の実験的サポートを提供しています。
要件
- トランザクションを追跡するために ClickHouse Keeper または ZooKeeper をデプロイする
- 原子データベースのみ (デフォルト)
- 非レプリケート MergeTree テーブルエンジンのみ
config.d/transactions.xml
に次の設定を追加して、実験的トランザクションサポートを有効にします:
ノート
- これは実験的な機能であり、変更が予想されます。
- トランザクション中に例外が発生した場合、トランザクションをコミットすることはできません。これは、タイプミスによって引き起こされた
UNKNOWN_FUNCTION
例外を含むすべての例外が対象です。 - ネストされたトランザクションはサポートされていません。現在のトランザクションを終了し、新しいトランザクションを開始してください。
設定
これらの例は、ClickHouse Keeper が有効になっている単一ノード ClickHouse サーバーを対象としています。
実験的トランザクションサポートの有効化
ClickHouse Keeper が有効になっている単一の ClickHouse サーバーノード用の基本設定
ClickHouse サーバーと適切なクォーラムの ClickHouse Keeper ノードをデプロイする詳細については、デプロイメント ドキュメントを参照してください。ここに示す設定は実験的な目的のためのものです。
例
実験的トランザクションが有効であることを確認する
BEGIN TRANSACTION
または START TRANSACTION
を発行し、続けて ROLLBACK
を実行して、実験的トランザクションが有効になっていることを確認します。また、ClickHouse Keeper がトランザクションを追跡するために使用されていることを確認します。
次のエラーが表示された場合は、構成ファイルを確認して、allow_experimental_transactions
が 1
(または 0
または false
以外の任意の値) に設定されていることを確認してください。
ClickHouse Keeper を次のコマンドで確認することもできます。
ClickHouse Keeper は imok
と応答する必要があります。
テスト用のテーブルを作成する
テーブルの作成はトランザクショナルではありません。このDDLクエリはトランザクションの外部で実行してください。
トランザクションを開始し、行を挿入する
トランザクション内からテーブルをクエリすると、行が挿入されたことが確認できますが、まだコミットされていません。
トランザクションをロールバックし、再度テーブルをクエリする
トランザクションがロールバックされたことを確認します:
トランザクションを完了し、再度テーブルをクエリする
トランザクションの内部調査
system.transactions
テーブルをクエリすることでトランザクションを確認できますが、トランザクションのセッションからそのテーブルをクエリすることはできません。別の clickhouse client
セッションを開いて、そのテーブルをクエリしてください。
詳細
詳細なテストや進捗状況を把握するには、この メタイシュー を参照してください。