DBAtlas · 数据库运维图谱

决策:选择哪种隔离级别?

事务隔离级别决定了并发与一致性之间的平衡。隔离级别越高,异常越少,但锁/冲突和重试越多。这棵决策树根据你能容忍哪些读异常(脏读、不可重复读、幻读),帮助你在 Read Committed、Repeatable Read/Snapshot 和 Serializable 之间做出选择。

你能容忍脏读吗?

从最基本的异常开始:一个事务是否应该能够读取尚未提交(且可能被回滚)的数据?几乎没有正经的应用需要这样;大多数现代引擎的默认设置已经阻止了脏读。只有在近似/分析性的粗略计数和追求极致速度时才会放宽。

  • 不,我只能读取已提交的数据
  • 是的,粗略/近似读取即可(少见)

在同一事务中再次读取时,必须看到相同的结果吗?

排除脏读之后,下一个问题是:如果在一个事务中两次读取同一行,因为有人在中间提交而看到不同的值(不可重复读),或出现新的行(幻读),对你来说是否有问题?需要报表/计算一致性的逻辑通常需要一致性快照。

  • 不,每条语句看到最新的已提交数据即可
  • 是的,整个事务需要一致性快照

并发事务在逻辑上必须完全有序吗?

你需要一致性读取;这样就够了吗,还是并发事务必须产生如同逐个顺序执行(可串行化)一样的结果?如果你能容忍写偏斜(write skew)这类微妙异常(例如两个事务读取不同的行,并以相互使对方失效的方式写入),Snapshot 就足够了;否则需要完全串行化。

  • 不,一致性快照即可
  • 是的,不能接受任何并发异常

建议:Read Uncommitted(仅限特殊情况)

最低的隔离级别;允许脏读。读取时几乎无需等待锁,但可能看到会被回滚的数据。不建议用于通用应用。

建议:Read Committed(OLTP 默认)

每条语句看到该时刻最新提交的数据;可防止脏读。它是大多数引擎的默认级别,为典型 OLTP 负载提供最佳的并发/一致性平衡。

建议:Repeatable Read / Snapshot(一致性读取)

事务在其开始时(或首次读取时)固定的一致性快照上工作;读取结果在事务期间不会改变。借助 MVCC,读不阻塞写,写也不阻塞读。

建议:Serializable(完全隔离)

最高的隔离级别:并发事务产生的结果如同串行执行(逐个顺序执行)一样。它防止所有读异常和写偏斜;代价是更多的冲突和重试需求。

在 DBAtlas 中打开 →