ケース1: MergeTree* ファミリーの1つのテーブルの1つのパーティションへの INSERT
- Atomic: INSERT は全体として成功するか、全体として拒否されます。クライアントに確認が返された場合はすべての行が挿入されており、クライアントにエラーが返された場合は1行も挿入されていません。
- Consistent: テーブルの制約に違反していない場合、INSERT 内のすべての行が挿入され、INSERT は成功します。制約に違反している場合は、1行も挿入されません。
- Isolated: 同時実行クライアントには、テーブルの一貫した snapshot、つまり INSERT 試行前のテーブルの state か、INSERT 成功後の state のいずれかが見え、途中の部分的な state は見えません。別の トランザクション の内部にいるクライアントは スナップショット分離、トランザクション の外部にいるクライアントは read uncommitted 分離レベルになります。
- Durable: 成功した INSERT は、クライアントに応答する前に、単一のレプリカまたは複数のレプリカ (
insert_quorumsetting で制御) 上の filesystem に書き込まれます。また ClickHouse は、OS に対して storage media 上の filesystem data の同期を要求できます (fsync_after_insertsetting で制御) 。 - materialized view が関係する場合、1つのステートメントで複数のテーブルに INSERT できます (クライアントからの INSERT 先は、関連する materialized view を持つテーブルです) 。
ケース2: MergeTree* ファミリーの単一テーブルの複数パーティションへの INSERT
- テーブルに多数のパーティションがあり、INSERT が複数のパーティションにまたがる場合、各パーティションへの挿入はそれぞれ個別のトランザクションとして扱われます
ケース3: MergeTree* ファミリーの1つの分散テーブルへのINSERT
- 分散テーブルへのINSERTは全体としてはトランザクションではありませんが、各分片への挿入はトランザクションです
ケース 4: Buffer table を使用する場合
- Buffer table への insert は、原子性、分離性、一貫性、耐久性のいずれも保証されません
ケース 5: async_insert を使用する場合
async_insertが有効で、wait_for_async_insertが 1 (デフォルト) に設定されている場合は、アトミック性が保証されます。一方、wait_for_async_insertが 0 に設定されている場合は、アトミック性は保証されません。
注意事項
- クライアントから特定のデータフォーマットで挿入された行は、次の場合に 1 つの ブロック に packed されます。
- insert フォーマットが行ベース (CSV、TSV、Values、JSONEachRow など) で、データの行数が
max_insert_block_size未満 (デフォルトでは約 1 000 000) であるか、並列パースを使用する場合 (デフォルトで有効) にデータサイズがmin_chunk_bytes_for_parallel_parsingバイト未満 (デフォルトでは 10 MB) である場合 - insert フォーマットがカラムベース (Native、Parquet、ORC など) で、データに含まれる ブロック が 1 つだけである場合
- insert フォーマットが行ベース (CSV、TSV、Values、JSONEachRow など) で、データの行数が
- 挿入される ブロック のサイズは、一般に多くの Settings に依存します (例:
max_block_size、max_insert_block_size、min_insert_block_size_rows、min_insert_block_size_bytes、preferred_block_size_bytesなど) - クライアントが server から応答を受け取れなかった場合、その トランザクション が成功したかどうかをクライアントは判断できず、exactly-once insertion の特性を利用して トランザクション を再試行できます
- ClickHouse は、同時実行 トランザクション のために内部で MVCC と スナップショット分離 を使用しています
- すべての ACID 特性は、server の kill/crash が発生した場合でも有効です
- 一般的な構成で durable inserts を確実にするには、異なる AZ に対する insert_quorum または fsync のいずれかを有効にする必要があります
- ACID における “consistency” は分散システムのセマンティクスまでは対象としていません。詳しくは https://jepsen.io/consistency を参照してください。これは別の Settings (select_sequential_consistency) で制御されます
- この説明では、複数の table、materialized view、複数の SELECT などにまたがるフル機能の トランザクション を可能にする新しい トランザクション 機能は扱っていません (次の「Transactions, Commit, and Rollback」セクションを参照してください)
トランザクション、コミット、ロールバック
要件
- トランザクションを追跡するため、ClickHouse Keeper または ZooKeeper をデプロイします
- Atomic DB のみ (デフォルト)
- Non-Replicated MergeTree テーブルエンジンのみ
config.d/transactions.xmlに次の設定を追加して、実験的なトランザクションサポートを有効にします。
注意事項
- これは実験的な機能であり、今後変更される可能性があります。
- トランザクション中に例外が発生した場合、そのトランザクションをコミットすることはできません。これには、タイプミスによって発生する
UNKNOWN_FUNCTION例外を含む、あらゆる例外が含まれます。 - ネストされたトランザクションはサポートされていません。代わりに、現在のトランザクションを終了してから新しいトランザクションを開始してください
設定
実験的なトランザクション機能を有効にする
/etc/clickhouse-server/config.d/transactions.xml
ClickHouse Keeper を有効にした単一の ClickHouse server ノード向けの基本構成
ClickHouse server と、適切なクォーラムを満たす ClickHouse Keeper ノードのデプロイについて詳しくは、デプロイメント のドキュメントを参照してください。ここで示す構成は試験的な目的のためのものです。
/etc/clickhouse-server/config.d/config.xml
例
Experimental な トランザクション が enabled であることを確認する
BEGIN TRANSACTION または START TRANSACTION を実行し、その後 ROLLBACK を実行して、Experimental な トランザクション と、トランザクション の追跡に使用される ClickHouse Keeper が有効になっていることを確認します。
テスト用のテーブルを作成
トランザクションを開始し、行を挿入する
トランザクション内からテーブルをクエリすると、まだコミットされていないにもかかわらず、その行が挿入されていることを確認できます。
トランザクションをロールバックし、再度テーブルをクエリする
トランザクションを完了し、テーブルに再度クエリを実行する
トランザクションの内部情報の確認
system.transactions テーブルをクエリするとトランザクションを確認できますが、トランザクション中のセッションからはその
テーブルをクエリできない点に注意してください。そのテーブルをクエリするには、2 つ目の clickhouse client セッションを開いてください。