关系型数据库一致性思考
作者:徐志斌
链接:https://www.zhihu.com/question/31346392/answer/51924208
来源:知乎
讲道理
定义:数据库一致性(Database Consistency)是指事务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。
数据库状态如何变化?每一次数据变更就会导致数据库的状态迁移。如果数据库的初始状态是C0,第一次事务T1的提交就会导致系统生成一个SYSTEM CHANGE NUMBER(SCN),这是数据库状态从C0转变成C1。执行第二个事务T2的时候数据库状态从T1变成T2,以此类推,执行第Tn次事务的时候数据库状态由C(n-1)变成Cn。
定义一致性主要有2个方面,一致读和一致写。
一致写:事务执行的数据变更只能基于上一个一致的状态,且只能体现在一个状态中。T(n)的变更结果只能基于C(n-1),C(n-2), ...C(1)状态,且只能体现在C(n)状态中。也就是说,一个状态只能有一个事务变更数据,不允许有2个或者2个以上事务在一个状态中变更数据。至于具体一致写基于哪个状态,需要判断T(n)事务是否和T(n-1),T(n-2),...T(1)有依赖关系。
一致读:事务读取数据只能从一个状态中读取,不能从2个或者2个以上状态读取。也就是T(n)只能从C(n-1),C(n-2)... C(1)中的一个状态读取数据,不能一部分数据读取自C(n-1),而另一部分数据读取自C(n-2)。实现读一致性之后,就实现了“可重复读”级别的隔离性。
摆事实
一致写:
定义100个事务T(1)...T(100)实现相同的逻辑 update table set i=i+1,i的初始值是0,那么并发执行这100个事务之后i的值是多少?可能很容易想到是100。那么怎么从一致性角度去理解呢?
数据库随机调度到T(50)执行,此时数据库状态是C(0),而其它事务都和T(50)有依赖关系,根据写一致性原理,其它事务必须等到T(50)执行完毕后数据库状态变为C(1)才可以执行。因此数据库利用锁机制阻塞其它事务的执行。直到T(50)执行完毕,数据库状态从C(0)迁移到C(1)。数据库唤醒其它事务后随机调度到T(89)执行,以此类推直到所有事务调度执行完毕,数据库状态最终变为C(100)。
一致读:
还是上面的例子,假设T(1)...T(100)顺序执行,在不同的时机执行select i from table,我们看到i的值是什么?
1. T(1)的执行过程中。数据库状态尚未迁移,读到的i=0
2. T(1)执行完毕,T(2)的执行过程中,数据库状态迁移至C(1),读到的i=1
原子性:记录之前的版本,允许回滚
一致性:事务开始和结束之间的中间状态不会被其他事务看到
隔离性:适当的破坏一致性来提升性能与并行度 例如:最终一致~=读未提交。
持久性:每一次的事务提交后就会保证不会丢失