数据库遵循的是两段锁协议,将事务分成两个阶段,加锁阶段和解锁阶段(所以叫两段锁)
- 加锁阶段:在该阶段可以进行加锁操作。在对任何数据进行读操作之前要申请并获得S锁(共享锁,其它事务可以继续加共享锁,但不能加排它锁),在进行写操作之前要申请并获得X锁(排它锁,其它事务不能再获得任何锁)。加锁不成功,则事务进入等待状态,直到加锁成功才继续执行。
- 解锁阶段:当事务释放了一个封锁以后,事务进入解锁阶段,在该阶段只能进行解锁操作不能再进行加锁操作。
事务的异常等级
事务的隔离级别是指:多个读写操作达到一定的隔离性要求。最高隔离级别是冲突可串行化。
串行化就是把同一个事务要做的读写操作按先后顺序排到一块。并发事务可以调整成串行化的话,就称为冲突可串行化。
例. 先导解释:r1(A),其中r代read表读操作,1代表事务1,A代表A类数据。w2(B),w代表write写操作,2代表事务2,B代表数据B。
r1(A)w1(A)r2(A)w2(A)r1(B)w1(B)r2(B)w2(B) 总共8个操作,2个事务并发执行。
在操作不冲突的情况下,变换可得:
r1(A)w1(A)r1(B)w1(B)r2(A)w2(A)r2(B)w2(B)
这就相当于执行了串行操作T1事务,T2事务。于是,这就是冲突可串行化。
如果不满足冲突可串行化,则会产生以下异常:
脏写
T1在T2提交前修改同一数据
脏读
T1在T2提交前读取T1修改的数据
T1 | T2 |
---|---|
开始事务 | |
开始事务 | |
查询账户余额为2000 | |
取款1000,余额1000 | |
查询账余额为1000(产生脏读) | |
取款异常,事务回滚,余额变更为2000 | |
收入2000,余额为3000 | |
提交事务 | |
备注:按正确逻辑,应为4000 |
不可重复读
T1在T2修改并提交前读取了同一数据项,且有可能再次读取同一数据项
T1 | T2 |
---|---|
开始事务 | |
开始事务 | |
查询账户余额为2000 | |
其他操作… | |
取款1000,余额1000 | |
提交事务 | |
第二次查询余额为1000(不可重复读) | |
备注:按正确逻辑,事务T1两次数据应该一致 |
幻读
Transaction T1 reads a set of data items satisfying some. Transaction T2 then creates data items that satisfy T1s and commits. If T1 then repeats its read with the same , it gets a set of data items different from the first read.
T1 | T2 |
---|---|
select * where dept =”Acct” //find(“sue”,”Acct”) and (“Tim”,”Acct”) |
|
insert (“Joe”,”Acct”) and commit | |
select * where dept =”Acct” //find(“sue”,”Acct”) and (“Tim”,”Acct”) and //(“Joe”,”Acct”) |
事物的隔离级别
防止产生不同等级的异常 对应 不同的隔离级别,但是都必须满足不产生脏写
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
read un-committed | 可能产生 | 可能产生 | 可能产生 |
read committed | / | 可能产生 | 可能产生 |
repeatable read | / | / | 可能产生 |
serializable | / | / | / |
隔离级别越高,提供的隔离性保障越强,并发能力也就越弱,实现代价很大,所以很多关系型数据库仅能做到RC级别,MySQL的默认隔离级别就是RC。
分布式系统的并发控制与一致性协议
并发控制
Ø 保证并发事务的多个操作之间不相互影响(事务的写入对并发事务的可见性)
Ø 对 并发事务间相互影响 的约束
Ø 以 隔离级别 作为衡量标准
一致性协议
Ø 保持多个副本数据的一致,即要求多副本上事务执行顺序是 一致的(事务的写入以何种顺序可见)
Ø 对 事务顺序 的约束
Ø 以 一致性级别 作为衡量标准
一个仅保证可串行化的系统在多副本环境下是正确的吗?
Ø 可串行化系统只保证一个串行的顺序,而对于具体的顺序并未加以限制
Ø 而分布式场景下,缺乏一个同步时钟,因此不同节点上操作顺序发生时 间错乱,该现象称为“time travel”
Ø time travel主要由主从数据库异步复制引起。
总结:没有任何一致性保证的隔离保证并不是特别有用,分布式系统中需要 两者结合共同保证数据库状态的正确性
更多实践内容参考 https://tech.meituan.com/2014/08/20/innodb-lock.html