一、事务(Transaction)的有关概念
1. 性质:ACID--Atomicity, Consistency, Isolation, Durability
2. BEGIGN TRANSACTION...Commit/Rollback(结束事务的两种方式:成功/不成功)
3. 事务的状态(五种):
begin transaction-->活动状态--end transaction-->部分提交状态--commit-->提交状态
--abort-->失败状态--rollback-->中止状态
4. 调度(Schedule):Serial/Concurrent(并行:分时的方法)
二、并发控制
并行调度无法保证事务之间的隔离性(Isolation),破坏数据库的一致性、正确性。
DBMS必须有一机制保证事务在并发的存取和修改数据的时候,integration不被破坏。
——>并发控制机制:在多用户环境下对数据库进行并发操作进行规范的机制。
可以改善系统的资源利用率、改善短事务的响应时间。
三种数据不一致性:
- 丢失修改
- 读dirty data
- 不可重复读
1. 丢失修改
T1:R(A) A=A+1,W(A)
T2: R(A) A=A-1,W(A)
2. 读脏数据: 某事务读到的数据与磁盘中该数据的值不一致
T1:R(A);A=A+1;W(A) ROLLBACK
T2: R(A)
3. 不可重复读:T1读取一个数据/某些数据,T2修改了该数据/插入或删除某些记录,T1以同样的方法读数据后,出现不一致
T1:R(A);R(B);R(C);C=A+B R(A);R(B);R(C);C=A+B
T2: R(A);A=A+1;W(A)
事务并发操作时,结果正确的唯一准则:可串行化(Serializable)
View Serializable; Conflict Serializable
三、并发控制的主要技术:封锁
1. 什么是封锁?
所谓封锁就是事务T在对某个数据对象例如表、记录等操作之前,先向系统发出请求,对其加锁。加锁后事务T就对该数据对象有了一定的控制,在事务T释放它的锁之前,其它的事务不能更新此数据对象。
T1 will operate A --> T1 asks the system to lock A -->if A is locked by T1's requiring, T1 will get some authenticaion of A --> Other T can not update A
2. 封锁类型(X/W; S)
X/W: Only T can read or update A. Others can not lock A/R(A)/W(A) with any locks until T unlocks A.
S/R: T and other Ts can read A. But all cannot update A. Other Ts can lock A with S.
锁的相容矩阵:
T2/T1 X S
X N N
S N Y
3. 封锁粒度——封锁对象的大小
In logic Units: Attributes, Tuples, Relation, Index, Database
In Physical Units: Page, Block
粒度大--并发度小--系统封锁开销小
粒度小--并发度大--系统封锁开销大
4. 封锁协议(Locking Protocol)
(1)在运用X锁和S锁这两种基本封锁,对数据对象加锁时,还需要约定一些规则,例如应何时申请X锁或S锁、持锁时间、何时释放等----这些规则即封锁协议
(2) 三级封锁协议
对并发操作的不正确调度可能会带来丢失修改、不可重复读和读“脏”数据等不一致性问题,三级封锁协议分别在不同程度上解决了这一问题。
不同级别的封锁协议达到的系统一致性级别是不同的。
一级封锁协议:事务T在修改数据R之前必须先对其加X锁,直到事务结束(Commit or Rollback)才释放。
防止丢失修改。
R(A)不需要加锁-->不能防止读脏数据和不可重复读。
二级封锁协议:一级封锁协议 + 事务T在读取数据R之前必须先对其加S锁,读完后即可释放S锁。
防止丢失修改,防止读“脏”数据。
读完数据后立即释放Slock-->不能防止不可重复读。
三级封锁协议是:一级封锁协议加上事务T在读取数据R之前必须先对其加S锁,直到事务结束才释放。
防止丢失修改,不读‘脏’数据外,防止不可重复读。
X | S | 一致性保证 | |||||
操作结束释放 | 事务结束释放 | 操作结束释放 | 事务结束释放 | 不丢失修改 | 不读脏数据 | 可重复读 | |
一级 | Y | Y | |||||
二级 | Y | Y | Y | Y | |||
三级 | Y | Y | Y | Y | Y |
举例:
一级 | T1: XLOCK(A), R(A), A=A-1, W(A), COMMIT, UNLOCK(A) T2: XLOCK(A),WAIT,WAIT.........WAIT,XLOCK(A),R(A),A=A-1,W(A),COMMINT,UNLOCKA | 没有丢失修改 |
T1: XLOCK(A),R(A),A=A-1,W(A) ROLLBACK,UNLOCK(A) T2: R(A) | 读脏数据 | |
T1: R(A),R(B),R(C),C=A+B, R(B),R(A),R(C),C=A+B T2: XLOCK(A),R(A),A=A+1,W(A),COMMIT,UNLOCK(A) | 不可重复读 | |
二级 | T1: SLOCK(A),R(A),UNLOCK(A),SLOCK(B),R(B),UNLOCK(B),SUM(A,B) T2: XLOCK(B),WAIT.........XLOCK(B),R(B),B=B+1,W(B),COMMIT,UNLOCK(B) | 不可重复读 |
(cont) | T1:SLOCK(A),R(A),UNLOCK(A),SLOCK(B),R(B),UNLOCK(B),SUM(A,B) | |
三级 | T1:SLOCK(A),R(A),SLOCK(B),R(B),SUM(A,B) T2: XLOCK(B),WAIT.................................................................................................... | |
(cont) | T1:R(A),R(B),SUM(A,B),COMMIT,UNLOCK(A),UNLOCK(B) T2:WAIT.......................................................................XLOCK(B),R(B),B=B+1,W(B),COMMIT,UNLOCK(B) | 可重复读 |
T1:SLOCK(A),R(A),A=A+1,W(A) ROLLBACK,UNLOCK(A) T2: XLOCK(A),WAIT.......................................XLOCK(A),R(A),A=A+1,W(A),COMMIT,UNLOCK(A) | 不读脏数据 |
5. 活锁和死锁
和操作系统一样,封锁的方法可能引起活锁和死锁。
活锁 | 如果事务T1封锁了数据R,事务T2又请求封锁R,于是T2等待。T3也请求封锁R,当T1释放了R上的封锁之后系统首先批准了T3的请求,T2仍然等待。然后T4又请求封锁R,当T3释放了R上的封锁之后系统又批准了T4的请求,......,T2有可能永远等待。 |
T1:Lock(R) Unlock(R) T2: Lock(R),Wait.................................................................................................................................... T3: Lock(R),Wait................................Lock(R) Unlock(R) T4: Lock(R),Wait,..................Lock(R) | |
如何避免? 先来先服务策略: 当多个事务请求服务同一数据对象时,按请求封锁的顺序对这些事务排队; 该数据上的锁一旦释放,首先批准申请队列中的第一个事务获得锁。 | |
死锁 | 如果事务T1封锁了数据R1,T2封锁了数据R2,然后T1又请求封锁R2,因T2已封锁了R2,于是T1等待T2释放R2上的锁。接着T2又申请封锁R1,因T1已封锁了R1,T2也只能等待T1释放R1上的锁。这样就出现了T1在等待T2,而T2又在等待T1的局面,T1和T2两个事务永远不能结束,形成死锁。 |
T1: Lock(R1), Lock(R2),Wait...................................................................................................... T2: Lock(R2), Lock(R1),Wait.................................................................. | |
解决方法(破坏产生死锁的条件) 1. 预防
2. 诊断与解除
|
6. Two-Phase Locking Protocol (2PL)
在对任何数据进行读写操作之前,事务必须先获得对该数据的封锁;
在释放一个封锁之后,事务不再获得任何其他封锁。
Serial-->Generated by 2PL-->Conflict Serializable-->View Serializable