隔离级别

ACID

  • A: Abortability
  • C 用户层面定义的 invariant
  • Isolation: 隔离性
  • Durability: 持久性

单对象写入的实现

希望对单个机器的单个节点,能提供原子性和隔离性

如果是大文件/覆盖的时候不 atomic(写到一半了) / 客户会不会看到部分更新的值

通过日志来实现崩溃回复,用锁实现隔离

单个对象实际上也有一些奇葩操作,比如 CAS 操作,一般直接由 CAS 类指令支持。

弱隔离级别

Read Committed

  • 读数据库:只能看到已经提交的数据,没有脏读
  • 写数据库:只会覆盖已经写入的数据,没有脏写

读未提交(Read uncommitted)。它可以防止脏写,但不防止脏读。

读:不会看到部分更新的值。

写:没有脏写

可能的实现:

实际上这个级别可以通过 row-level-lock 实现:

修改特定 object 的时候,只有说,直到 abort/commit

读可以拿到对应的锁,实际上也可以保留一份 old value, 以操作。

SI 和 Repeatable Read

这个时候需要说 Read Committed 的问题:它读到的可能是自己的 Write 和别人 Committed 的 write 的混合物

这种异常被称为不可重复读/读偏差(read skew)

实现的方法相对来说可能要备份/SI

SI

  • 写需要写锁,读从 Snapshot 读

Txn 从一致性快照读取

在 PostgreSQL 中

  • 事务会有一个严格递增的 ID
  • 字段有 createBy deleteBy 的语义,实现上是 xmin, xmax.

SI 有可见性的规则:

  • 每次事务开始的时候,列出其他所有的Txn, 并 ignore 这些
  • 被 abort 的事务执行的写入被忽略
  • 被较晚事务 id(产生第一次读/读之前获取的)事务所做的任何写入都会被忽略,不管是否已经提交

所以可见性规则是:

  • txn 开始的时候,创建对象的事务已经提交了
  • 对象没有被被标记为 deleted

SI && Index

  • PostgreSQL 避免更新
  • TiDB Index 类型会一起更新
  • 有的数据库会创建 Copy-on-write 结构
  • PostgreSQL: SI —> repeatable read
  • Oracle: Serializable

Lost Update

  • TXN1 readX writeX commit
  • TXN2 readX writeX commit

Txn1 有可能会被 Overwrite.

可以实现原子写,也可以 LOCK FOR XXX 显示锁定。

SI 可能发生的问题

  • 3个 txn 互相依赖
  • 2个之间的 phantom