通过


隔离级别(WriteSerializable 和 Serializable)

Azure Databricks 上的 Delta Lake 支持两个隔离级别,这些隔离级别控制给定表上的并发操作的交互方式:

隔离级别 说明
序列 化 最强隔离级别。 确保已提交的写入操作和所有读取都是 可序列化的。 只要有一个串行序列,就允许执行一次操作,从而生成与表中所示相同的结果。 对于写入操作,此串行序列与表历史记录中看到的顺序相同。
WriteSerializable (默认) 比 Serializable 更弱的隔离级别。 确保仅写入操作(而非读取操作)是可序列化的。 这仍然比 快照 隔离更强。 为最常见的操作提供数据一致性和可用性的良好平衡。

隔离级别如何影响读取

读取操作始终使用快照隔离。 写入隔离级别确定读取器是否可以查看表的快照,该快照根据历史记录“从未存在”。

  • 可序列化:读取器始终只看到符合历史记录的表
  • WriteSerializable:读取器可能会看到 Delta log 中并不存在的表状态

示例:并发删除和插入

假设长时间运行的删除事务和插入事务同时启动并读取版本 v0。 插入事务首先提交并创建版本 v1。 然后,删除事务会尝试提交 v2

t0: deleteTxn_START
t1: insertTxn_START
t2: insertTxn_COMMIT(v1)
t3: deleteTxn_COMMIT(v2)

在此方案中, deleteTxn 看不到插入 insertTxn 的数据,也没有删除它们:

  • 可序列化deleteTxn 不允许进行提交,因为发生了冲突
  • WriteSerializabledeleteTxn 被允许提交,因为事务可以被排序。 生成的表状态就像insertTxn发生在deleteTxn之后一样,因此插入的行成为表的一部分。 但是,Delta 历史记录显示物理提交顺序(insertTxn 在 v1,deleteTxn 在 v2)。

设置隔离级别

使用 ALTER TABLE 以下命令设置隔离级别:

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

其中 <level-name>SerializableWriteSerializable

Example:

-- Change from default WriteSerializable to Serializable
ALTER TABLE my_table SET TBLPROPERTIES ('delta.isolationLevel' = 'Serializable')

Delta Lake 何时提交而不读取表?

如果满足以下条件,Delta Lake INSERT 或追加操作在提交之前不会读取表状态:

  1. 逻辑可以通过 INSERT SQL 逻辑或追加模式来表示
  2. 逻辑不包含引用写入操作目标表的子查询或条件

与其他提交一样,Delta Lake 使用事务日志元数据在提交时验证和解析表版本,但实际上不会读取该表的版本。

注释

许多常见模式使用 MERGE 操作来根据表条件插入数据。 尽管可以使用 INSERT 语句重写此逻辑,但如果任何条件表达式引用目标表中的某一列,则这些语句要遵守与 MERGE 相同的并行限制。

后续步骤