iceberg 的 snapshot isolation 是一种基于已提交快照的读一致性机制,而非传统数据库的事务隔离级别;它通过绑定查询到特定 snapshot 提供稳定、可重现的只读视图,不支持行级更新、多语句事务或脏读/不可重复读控制。

SQL Iceberg 的 snapshot isolation 并非传统数据库意义上的“隔离级别”(如 READ COMMITTED、SERIALIZABLE),而是一种基于快照(snapshot)的**读一致性机制**,其设计目标是为分布式、不可变数据湖表提供时间点一致的查询视图。它和传统 OLTP 数据库中的隔离级别在语义、实现方式与适用场景上存在本质差异。
Snapshot isolation 是读一致性保障,不是事务隔离控制
Iceberg 的 snapshot isolation 指的是:每个查询自动绑定到某个已提交的 snapshot(即某次 commit 后的表状态),读取该 snapshot 对应的文件列表和元数据,从而获得**稳定、可重现、不被并发写入干扰的读视图**。它不解决写-写冲突(如更新同一行),因为 Iceberg 表默认不可原地更新;也不提供跨语句的事务可见性控制(如防止幻读),因为 Iceberg 本身不支持多语句事务(单条 INSERT/UPDATE/MERGE 是原子 commit,但不构成 ACID 事务上下文)。
常见操作中:
- SELECT 查询默认读取最新 snapshot,但可通过
AS OF TIMESTAMP或VERSION AS OF显式指定历史 snapshot - 并发写入(如两个 Spark 作业同时向同一表 INSERT)通过乐观并发控制(OCC)协调:各自基于某个 snapshot 构建新 snapshot,提交时校验 base snapshot 是否仍有效,冲突则重试
- 没有“未提交读”“不可重复读”等现象,因为所有读都面向已提交的 snapshot,天然规避了脏读和不可重复读
对比传统数据库的隔离级别
传统关系型数据库(如 PostgreSQL、SQL Server)的隔离级别作用于**行级锁 + MVCC 版本链 + 事务时间戳**,用于协调多个并发事务对同一数据集的读写竞争。例如:
- READ COMMITTED:每条 SELECT 语句看到语句开始时刻已提交的数据,允许不可重复读
- REPEATABLE READ:整个事务内多次 SELECT 看到相同快照,但可能有幻读(PostgreSQL 实际用 snapshot isolation 实现,接近 SERIALIZABLE)
- SERIALIZABLE:最高级别,通过谓词锁或 SSI 防止所有异常现象
Iceberg 不提供这些语义——它不维护行级版本链,不支持 UPDATE/DELETE 语句级别的可见性切换,也没有“当前事务中后续语句是否看到前序语句写入”的问题(因写入即 commit,且读写分离)。
Iceberg 的“版本”本质是不可变快照链
Iceberg 表的每次成功写入(INSERT/UPDATE/MERGE/DELETE)都会生成一个新 snapshot,并追加到 snapshot 链中。每个 snapshot 包含:
- 唯一 ID 和时间戳
- 引用的 manifest 列表(描述哪些数据文件有效)
- 父 snapshot ID(形成链式结构)
这种设计让“版本回溯”极轻量:查询旧版本只需解析对应 snapshot 的元数据,无需复制或恢复数据文件。这也意味着 Iceberg 的“版本隔离”是**静态、只读、离散的**,而非传统数据库中动态、可读可写的事务视图。
实际使用中的关键区别总结
当你在 Iceberg 中说“我用了 snapshot isolation”,真实含义是:
- 你依赖 Iceberg 自动提供的读一致性,无需手动设置 SET TRANSACTION ISOLATION LEVEL
- 你通过 time travel(
FOR SYSTEM_TIME AS OF)或 snapshot ID 显式选择版本,而不是靠隔离级别隐式控制可见性 - 写入并发安全由乐观锁(基于 snapshot ID 比较)保证,而非锁协议或隔离级别规则
- 无法实现传统意义上“一个事务中先读再写再读”的一致性语义(因无跨语句事务上下文)
所以 Iceberg 的 snapshot isolation 是数据湖场景下的务实设计:放弃复杂事务语义,换取高并发、可扩展、可审计的不可变数据管理能力。










