分離レベルIsolation Levels

テーブルの分離レベルでは、同時実行トランザクションによって行われた変更からトランザクションを分離する必要がある程度を定義します。The isolation level of a table defines the degree to which a transaction must be isolated from modifications made by concurrent transactions. Delta Lake on Azure Databricks では、Serializable と Writを可能にする2つの分離レベルがサポートされています。Delta Lake on Azure Databricks supports two isolation levels: Serializable and WriteSerializable.

  • Serializable: 最も強力な分離レベルです。Serializable: The strongest isolation level. これにより、コミットされた書き込み操作とすべての読み取りをシリアル化できるようになります。It ensures that committed write operations and all reads are Serializable. 操作は、テーブルに表示されるのと同じ結果を生成する、一度に1つずつ実行するシリアルシーケンスが存在する限り許可されます。Operations are allowed as long as there exists a serial sequence of executing them one-at-a-time that generates the same outcome as that seen in the table. 書き込み操作の場合、シリアルシーケンスは、テーブルの履歴で見られるものとまったく同じです。For the write operations, the serial sequence is exactly the same as that seen in the table’s history.

  • Writeserializable (既定値) : Serializable よりも弱い分離レベル。WriteSerializable (Default): A weaker isolation level than Serializable. 書き込み操作 (つまり、読み取りではない) のみがシリアル化可能であることが保証されます。It ensures only that the write operations (that is, not reads) are serializable. ただし、これはスナップショット分離よりも強力です。However, this is still stronger than Snapshot isolation. データの一貫性と、ほとんどの一般的な操作での可用性のバランスを保つことができるため、既定の分離レベルが実現されています。WriteSerializable is the default isolation level because it provides great balance of data consistency and availability for most common operations.

    このモードでは、デルタテーブルの内容が、テーブル履歴に表示される一連の操作と異なる場合があります。In this mode, the content of the Delta table may be different from that which is expected from the sequence of operations seen in the table history. これは、このモードでは、x の後に Y がコミットされたことが示されていても、x の前に y が実行された場合 (つまり、操作 X と Y) の特定のペアが実行されるためです。この順序変更を禁止するには、テーブルの分離レベルを Serializable に設定して、これらのトランザクションが失敗するようにします。This is because this mode allows certain pairs of concurrent writes (say, operations X and Y) to proceed such that the result would be as if Y was performed before X (that is, serializable between them) even though the history would show that Y was committed after X. To disallow this reordering, set the table isolation level to be Serializable to cause these transactions to fail.

分離レベルを 設定する Set the isolation level

分離レベルは、ALTER TABLE コマンドを使用して設定します。You set the isolation level using the ALTER TABLE command.

ALTER TABLE <table-name> SET TBLPROPERTIES ('delta.isolationLevel' = <level-name>)

<level-name>Serializable または WriteSerializablewhere <level-name> is Serializable or WriteSerializable.

たとえば、分離レベルを既定の WriteSerializable から Serializable に変更するには、次のように実行します。For example, to change the isolation level from the default WriteSerializable to Serializable, run:

ALTER TABLE <table-name> SET TBLPROPERTIES ('delta.isolationLevel' = 'Serializable')

書き込みの競合Write conflicts

次の表では、各分離レベルで競合する可能性がある書き込み操作のペアについて説明します。The following table describes which pairs of write operations can conflict in each isolation level.

INSERTINSERT UPDATE、DELETE、MERGE INTOUPDATE, DELETE, MERGE INTO 最適化OPTIMIZE
INSERTINSERT 競合できませんCannot conflict
UPDATE、DELETE、MERGE INTOUPDATE, DELETE, MERGE INTO Serializable で競合する可能性があります。Can conflict in Serializable, cannot conflict in WriteSerializable シリアル化可能な & の整合性を持つことができます。Can conflict in Serializable & WriteSerializable
最適化OPTIMIZE 競合できませんCannot conflict シリアル化可能な & の整合性を持つことができます。Can conflict in Serializable & WriteSerializable シリアル化可能な & の整合性を持つことができます。Can conflict in Serializable & WriteSerializable

パーティション分割と不整合コマンド条件を使用して競合を回避するAvoid conflicts using partitioning and disjoint command conditions

"競合を可能にする" とマークされているすべてのケースで、2つの操作が競合するかどうかは、同じファイルセットを操作するかどうかによって異なります。In all cases marked “can conflict”, whether the two operations will conflict depends on whether they operate on the same set of files. この2つのファイルセットを結合解除するには、操作の条件で使用されるものと同じ列でテーブルをパーティション分割します。You can make the two sets of files disjoint by partitioning the table by the same columns as those used in the conditions of the operations. たとえば、テーブルが日付によってパーティション分割されていない場合、2つのコマンド UPDATE table WHERE date > '2010-01-01' ...DELETE table WHERE date < '2010-01-01' が競合します。これは、両方とも同じファイルのセットを変更しようとするためです。For example, the two commands UPDATE table WHERE date > '2010-01-01' ... and DELETE table WHERE date < '2010-01-01' will conflict if the table is not partitioned by date, as both can attempt to modify the same set of files. @No__t_0 によってテーブルをパーティション分割すると、競合が回避されます。Partitioning the table by date will avoid the conflict. このため、コマンドで一般的に使用される条件に従ってテーブルをパーティション分割すると、競合が大幅に減少する可能性があります。Hence, partitioning a table according to the conditions commonly used on the command can reduce conflicts significantly. ただし、大量のカーディナリティがある列でテーブルをパーティション分割すると、多数のサブディレクトリが原因で他のパフォーマンスの問題が発生する可能性があります。However, partitioning a table by a column that has high cardinality can lead to other performance issues due to large number of subdirectories.

競合の例外Conflict exceptions

トランザクションの競合が発生すると、次のいずれかの例外が発生します。When a transaction conflict occurs, you will observe one of the following exceptions.

ConcurrentAppendExceptionConcurrentAppendException

トランザクションがパーティション内のレコードを更新し、同時実行トランザクションによって同じパーティション内のレコードも更新される場合。When a transaction updates records in a partition and a concurrent transaction also updates records in the same partition. 分離レベルが Serializable に設定されている場合、トランザクションによって読み取られるパーティションディレクトリに追加すると、このエラーが発生します。When the isolation level is set to Serializable, any append to a partition directory that your transaction reads would cause this error. 分離レベルが WriteSerializable に設定されている場合、操作によって読み取られたパーティションに更新 (DELETEUPDATE、または MERGE のためにファイルが書き直された) 場合にのみ、トランザクションが競合します。When the isolation level is set to WriteSerializable, then your transaction will conflict only if there was an update (files were rewritten due to DELETE, UPDATE, or MERGE) to a partition your operation was reading.

この例外は、通常、同時 MERGE 操作中にスローされます。This exception is typically thrown during concurrent MERGE operations. 同時実行操作は個別のパーティションディレクトリで物理的に作業している場合がありますが、MERGE 条件でこの分離が明示的に指定されていないと、操作が競合する可能性があります。While the concurrent operations may be physically working on separate partition directories, the operations may conflict unless this separation is explicit in the MERGE condition. 各データ メンバー フィールドが JSON オブジェクトにマップされ、フィールド名がオブジェクトの "key" 部分にマップされ、"value" 部分がオブジェクトの値の部分に再帰的にマップされます。Consider the following example.

date = dbutils.widgets.get('date')
country = dbutils.widgets.get('country')
# Read the json data for a given country at a given date
spark.read.json('/source/path/date=%s/country=%s' % (date, country)).createOrReplaceTempView('source_table')

# Target 'delta_table' is also partitioned by date and country
spark.sql("""
    MERGE INTO delta_table d
    USING source_table s
    ON s.user_id = d.user_id AND s.date = d.date AND s.country = d.country
    WHEN MATCHED THEN UPDATE SET *
    WHEN NOT MATCHED THEN INSERT *
    """)

上記の Python notebook を Azure Databricks ジョブとして実行し、異なる日付または国を同時にスケジュールするとします。Suppose you run the above Python notebook as an Azure Databricks job, and you schedule different dates or countries concurrently. 各ジョブはターゲットデルタテーブルの独立したパーティションで動作しているため、競合は発生しません。Since each job is working on an independent partition on the target Delta table, you don’t expect any conflicts. ただし、この条件は、残念ながら明示的には不十分であるため、競合が発生する可能性があります。However the condition is unfortunately not explicit enough, and may result in a conflict. 代わりに、ステートメントを次のように書き換えることができます。Instead, you can rewrite your statement as:

# Note how the date and country are filled in for the target table.
spark.sql("""
    MERGE INTO delta_table d
    USING source_table s
    ON s.user_id = d.user_id AND d.date = '%s' AND d.country = '%s'
    WHEN MATCHED THEN UPDATE SET *
    WHEN NOT MATCHED THEN INSERT *
    """ % (date, country))

ConcurrentDeleteReadExceptionConcurrentDeleteReadException

同時実行トランザクションでは、トランザクションによって読み取られたファイルが削除されます。A concurrent transaction deletes a file that your transaction read. 一般的な原因は、ファイルを書き換える DELETEUPDATE、または MERGE 操作です。Common causes are a DELETE, UPDATE, or MERGE operation that rewrites files.

ConcurrentDeleteDeleteExceptionConcurrentDeleteDeleteException

同時実行トランザクションでは、トランザクションによって削除されるファイルも削除されます。A concurrent transaction deletes a file that your transaction also deletes. 2つの同時 OPTIMIZE ジョブによって、同じファイルが最適化されていることが原因である可能性があります。This could be caused by two concurrent OPTIMIZE jobs optimizing the same files.

MetadataChangedExceptionMetadataChangedException

同時実行トランザクションによって、デルタテーブルのメタデータが更新されます。A concurrent transaction updates the metadata of a Delta table. 一般的な原因としては、ALTER TABLE 操作や、テーブルのスキーマを更新するデルタテーブルへの書き込みがあります。Common causes are ALTER TABLE operations or writes to your Delta table that update the schema of the table.

ConcurrentTransactionExceptionConcurrentTransactionException

同じチェックポイントの場所を使用するストリーミングクエリが同時に複数回開始され、同時にデルタテーブルへの書き込みを試行する場合。If a streaming query using the same checkpoint location is started multiple times concurrently and tries to write to the Delta table at the same time. 2つのストリーミングクエリで同じチェックポイントの場所を使用し、同時に実行することはできません。You should never have two streaming queries use the same checkpoint location and run at the same time.

ProtocolChangedExceptionProtocolChangedException

差分テーブルを新しいバージョンにアップグレードする場合。When your Delta table is upgraded to a new version. 将来のトランザクションを成功させるには、クラスターのバージョンをアップグレードする必要がある場合があります。You may need to upgrade your cluster version for future transactions to succeed. 詳細については、「テーブルのバージョン」を参照してください。See table versions for more details.