トランザクション(ACID)対応
ケース 1: MergeTree* ファミリーの 1 つのテーブルの 1 つのパーティションへの INSERT
挿入される行が 1 つのブロックとしてまとめて挿入される場合(注を参照)、これはトランザクション特性(ACID)を満たします:
- 原子性 (Atomic): INSERT は全体として成功するか拒否されます。クライアントに成功の確認応答が送信された場合は、すべての行が挿入されています。クライアントにエラーが送信された場合は、どの行も挿入されていません。
- 一貫性 (Consistent): テーブル制約に違反がなければ、INSERT 内のすべての行が挿入され、INSERT は成功します。制約に違反した場合は、どの行も挿入されません。
- 分離性 (Isolated): 同時実行中のクライアントはテーブルの一貫したスナップショットを観測します。つまり、INSERT 実行前のテーブル状態か、成功した INSERT の後の状態のいずれかであり、中間的な状態は見えません。別のトランザクション内のクライアントはスナップショット分離を持ち、トランザクション外のクライアントは読み取り未コミット (read uncommitted) 分離レベルになります。
- 永続性 (Durable): 成功した INSERT は、クライアントに応答する前にファイルシステムに書き込まれます。これは単一レプリカまたは複数レプリカ(
insert_quorum設定で制御)に対して行われ、ClickHouse は OS に対してストレージメディア上のファイルシステムデータの同期を要求できます(fsync_after_insert設定で制御)。 - マテリアライズドビューが関与している場合、1 つのステートメントで複数のテーブルに対する INSERT が可能です(クライアントからの INSERT は、関連するマテリアライズドビューを持つテーブルに対して行われます)。
ケース 2: MergeTree* ファミリーの 1 つのテーブルに対する、複数パーティションへの INSERT
上記のケース 1 と同様ですが、次の点が異なります:
- テーブルに多数のパーティションがあり、INSERT が多くのパーティションにまたがる場合、各パーティションへの挿入はそれぞれ独立したトランザクションとして扱われます
ケース 3: MergeTree* ファミリーの 1 つの分散テーブルへの INSERT
上のケース 1 と同様ですが、次の点が異なります:
- Distributed テーブルへの INSERT は全体としてはトランザクションとして扱われませんが、各シャードへの挿入はトランザクションとして扱われます
ケース 4: Buffer テーブルの使用
- Buffer テーブルへの INSERT 操作では、アトミック性 (Atomicity)、分離性 (Isolation)、一貫性 (Consistency)、永続性 (Durability) のいずれも保証されません
ケース5: async_insert の使用
上記のケース1と同様ですが、次の点が異なります:
async_insertが有効で、wait_for_async_insertが 1(デフォルト)に設定されている場合にはアトミック性が保証されますが、wait_for_async_insertが 0 に設定されている場合にはアトミック性は保証されません。
Notes
- クライアントからあるデータフォーマットで挿入された行は、次の場合に 1 つのブロックにまとめられます:
- 挿入フォーマットが行ベース(CSV、TSV、Values、JSONEachRow など)の場合で、データが
max_insert_block_size行(デフォルトでは約 1 000 000 行)未満、または並列パースを使用する場合(デフォルトで有効)にはmin_chunk_bytes_for_parallel_parsingバイト(デフォルトでは 10 MB)未満であるとき - 挿入フォーマットがカラムベース(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など) - クライアントがサーバーから応答を受け取らなかった場合、トランザクションが成功したかどうかクライアントには分からないため、exactly-once 挿入特性を利用してトランザクションを再実行できます
- ClickHouse は並行トランザクションの内部処理において MVCC と snapshot isolation を使用しています
- サーバーが kill されたりクラッシュした場合でも、ACID のすべての特性は保持されます
- 典型的な構成で永続的な INSERT を保証するには、異なるアベイラビリティゾーン(AZ)への
insert_quorumかfsyncのいずれかを有効化する必要があります - ACID における「一貫性」は分散システムのセマンティクスを対象としていません。分散システムの一貫性については https://jepsen.io/consistency を参照してください。これは(
select_sequential_consistencyなどの)別の設定によって制御されます - この説明では、複数テーブルやマテリアライズドビュー、複数の SELECT などに対してフル機能のトランザクションを提供する新しいトランザクション機能は扱っていません(次の「Transactions, Commit, and Rollback」のセクションを参照してください)
トランザクション、コミット、ロールバック
このドキュメントの冒頭で説明した機能に加えて、ClickHouse にはトランザクション、コミット、ロールバック機能に対する実験的なサポートがあります。
要件
- トランザクションを追跡するために ClickHouse Keeper または ZooKeeper をデプロイする
- Atomic DB のみ(デフォルト)
- 非 Replicated MergeTree テーブルエンジンのみ
config.d/transactions.xmlに次の設定を追加して、トランザクションの実験的サポートを有効にする:
注意事項
- これは実験的な機能であり、今後変更される可能性があります。
- トランザクション中に例外が発生した場合、そのトランザクションをコミットすることはできません。これは、タイプミスによる
UNKNOWN_FUNCTION例外を含むすべての例外が対象です。 - ネストされたトランザクションはサポートされません。現在のトランザクションを終了してから、新しいトランザクションを開始してください。
設定
これらの例は、ClickHouse Keeper を有効にした単一ノードの ClickHouse サーバーを前提としています。
トランザクションの実験的サポートを有効にする
ClickHouse Keeper を有効にした単一の ClickHouse サーバーノード向け基本構成
ClickHouse サーバーおよび適切な ClickHouse Keeper ノードのクォーラムのデプロイ方法についての詳細は、deployment に関するドキュメントを参照してください。ここで示す構成は実験・検証目的のものです。
例
実験的トランザクション機能が有効になっていることを確認する
BEGIN TRANSACTION または START TRANSACTION を発行し、続けて ROLLBACK を実行して、実験的トランザクション機能が有効であること、およびトランザクションの追跡に使用される ClickHouse Keeper が有効であることを確認します。
次のエラーが表示された場合は、設定ファイルを確認し、allow_experimental_transactions が 1(または 0 や false 以外の値)に設定されていることを確認してください。
次のコマンドを実行して ClickHouse Keeper の状態を確認することもできます。
ClickHouse Keeper は imok と応答するはずです。
テスト用のテーブルを作成する
テーブルの作成はトランザクションとして実行されません。DDL クエリはトランザクションの外で実行してください。
トランザクションを開始して 1 行を挿入する
トランザクション内でテーブルに対してクエリを実行すると、まだコミットされていないにもかかわらず行が挿入されていることを確認できます。
トランザクションをロールバックし、再度テーブルをクエリする
トランザクションがロールバックされていることを確認します。
トランザクションを完了してからテーブルを再度クエリする
トランザクションの調査
system.transactions テーブルをクエリしてトランザクションを確認できます。ただし、そのテーブルはトランザクション中のセッションからはクエリできない点に注意してください。そのテーブルをクエリするには、別の clickhouse client セッションを開いてください。
詳細情報
より包括的なテスト内容や進捗の最新情報については、この meta issue を参照してください。