本文主要是以ANSI SQL-92的隔离级别定义进行展开,并阐述为什么ANSI SQL-92的致命伤。
首先是ANSI SQL-92标准定义的隔离级别及相关的读现象:
隔离级别 | 脏读 | 不可重复读 | 幻影读 |
---|---|---|---|
未提交读 | 可能发生 | 可能发生 | 可能发生 |
提交读 | - | 可能发生 | 可能发生 |
可重复读 | - | - | 可能发生 |
可序列化 | - | - | - |
如果对《数据库系统概念》或cmu 15-445熟悉的话,那么肯定知道如何去使用SS2PL来构建可序列化
的隔离级别,并且可能听过Write Skew
现象,相关的示例如下(以PingCAP公众号中的文章《事务前沿研究隔离级别的追溯与究明,带你读懂 TiDB 的隔离级别(上篇)》中的例子为例):
Txn1 | Txn2 |
---|---|
r(x, 10) | |
r(y, 20) | |
w(y, 10) | |
w(x, 20) | |
commit | commit |
r(x, 20) | |
r(y, 10) |
这个例子虽然满足是没有脏读,没有不可重复读,没有幻读,但是我们知道这个schedule一定不是serializable,这是因为Txn1中的r(x, 10)会和Txn2中的w(x, 20)产生RW冲突,同理这两个事务也会关于y产生冲突,无法可序列化的;并且即使可序列化,那么Txn1中的w(y, 10)会因为Txn2中的r(y, 20)已经对y上了S锁从而产生等待;
那么问题就很明显了,ANSI SQL-92存在的问题就是:我们可以从某个隔离级别推断是其是否可能发生脏读、不可重复读、幻读,但是不能反推:即没有脏读、幻读、不可能重复读那么就是XXX隔离级别,然后这样存在的问题就是,某些读写异常的情况在读未提交、读已提交、可重复读、可串行化并没有涵盖完全。