隔离级别
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