Delta Lake on Azure Databricks では、特定のテーブルに対する同時実行操作の対話方法を制御する 2 つの分離レベルがサポートされています。
| 分離レベル | 説明 |
|---|---|
| シリアライズ可能 | 最も強力な分離レベル。 コミットされた書き込み操作とすべての読み取りが シリアル化可能であることを確認します。 一度に 1 つずつ実行すると、テーブルに表示されるのと同じ結果を生成するシリアル シーケンスがある限り、操作は許可されます。 書き込み操作の場合、このシリアル シーケンスはテーブルの履歴に表示される順序と同じです。 |
| WriteSerializable (既定) | Serializable よりも分離レベルが弱い。 書き込み操作 (読み取り不可) のみをシリアル化できるようにします。 これは、 スナップショット 分離よりも依然として強力です。 最も一般的な操作に対して、データの一貫性と可用性のバランスを取ります。 |
アイソレーションレベルを変更するタイミング
ほとんどのワークロードではデフォルトのWriteSerializable分離レベルを維持してください。
WriteSerializable では、同時実行挿入より先に始まる DELETE、UPDATE、または MERGE でも、その後でコミットすることができます。 インサートの行は、たとえ操作条件に合っていても影響を受けません。 テーブル履歴は依然として挿入が先に記載されるため、テーブルの内容は履歴順にコミットを再生した結果と一致しません。 例: 同時削除と挿入を参照。
この結果を受け入れられない場合は、テーブルをSerializableに変更してください。 たとえば、DELETE が、コミット時に存在するすべての一致する行を削除する必要がある場合や、ダウンストリーム プロセスが履歴内のコミット順序からテーブル コンテンツを再構築する場合です。 Serializableでは、後の操作が競合で失敗し、再試しをしなければなりません。
Serializable では、並行書き込みのスループットが低下します。 テーブルを読み取らない追加操作はWriteSerializableでは競合しませんが、Serializableでは競合する可能性があります。 行レベルのコンカレンシーを参照してください。
分離レベルが読み取りに与える影響
読み取り操作では、常にスナップショット分離が使用されます。 書き込み分離レベルは、履歴に従って "存在しなかった" テーブルのスナップショットを閲覧者が表示できるかどうかを決定します。
- シリアル化可能: リーダーは常に履歴に準拠するテーブルのみを表示します
- WriteSerializable: 閲覧者は、Delta ログに存在しないテーブルの状態を確認できます
例: 同時削除と挿入
実行時間の長い削除トランザクションと挿入トランザクションが同時に開始され、バージョン v0を読み取るシナリオについて考えてみましょう。 挿入トランザクションは最初にコミットされ、バージョン v1が作成されます。 その後、削除トランザクションは v2コミットを試みます。
t0: deleteTxn_START
t1: insertTxn_START
t2: insertTxn_COMMIT(v1)
t3: deleteTxn_COMMIT(v2)
このシナリオでは、deleteTxninsertTxnによって挿入されたデータが表示されず、削除されませんでした。
-
Serializable:
deleteTxnはコミットできず、競合が発生しています -
WriteSerializable: トランザクションを並べ替えることができるため、
deleteTxnによるコミットが許可されます。 結果のテーブルの状態は、insertTxn後deleteTxn発生したかのように、挿入された行がテーブルの一部になります。 ただし、差分履歴は、物理的なコミット順序を示します (v2 のinsertTxn前の v1 のdeleteTxn)。
分離レベルを設定する
アイソレーションレベルを設定するには、 ALTER TABLE コマンドを使用します:
ALTER TABLE <table-name> SET TBLPROPERTIES ('delta.isolationLevel' = <level-name>)
<level-name>がSerializableまたはWriteSerializableされている場合。
Example:
-- Change from default WriteSerializable to Serializable
ALTER TABLE my_table SET TBLPROPERTIES ('delta.isolationLevel' = 'Serializable')
テーブルを読み取らずに Delta Lake がコミットするタイミング
Delta Lake の INSERT 操作または追加操作では、次の条件が満たされている場合、コミット前にテーブルの状態を読み取りません。
- ロジックは、 SQL ロジックまたは追加モードを使用して表されます
- ロジックには、書き込み操作の対象となるテーブルを参照するサブクエリまたは条件は含まれていません。
他のコミットと同様に、Delta Lake はトランザクション ログ メタデータを使用して、コミット時にテーブルのバージョンを検証および解決しますが、実際にはテーブルのバージョンは読み取われません。
注
多くの一般的なパターンで、MERGE 操作を使用して、テーブルの状態に基づいてデータが挿入されます。
INSERT ステートメントを使用してこのロジックを書き換えることは可能ですが、いずれかの条件式がターゲット テーブル内の列を参照する場合、これらのステートメントにも MERGE と同じコンカレンシーの制限事項があります。