我们今天继续来看数据库原理,我们简单讲讲数据库的并发控制。
并发控制的定义
并发控制是为了保证事务的隔离性和一致性,数据库管理系统需要对并发操作进行正确调度。并发控制的主要技术有:、时间戳、乐观控制法、多版本并发控制等。
并发操作带来的数据不一致性主要有以下三点:
- 丢失修改:两个事务T1和T2 读入同一数据并修改,T2 提交的结果破坏了 T1提交的结果,导致T1 的修改被丢失。
- 不可重复读:指事务T1读取数据后,事务T2 执行更新操作,使T1 无法再现前一次读取结果。
- 读脏数据:事务T1 修改某一数据后并将其写回磁盘,事务T2读取同一数据后,T1 由于某种原因被撤销,这时T1 修改过的数据恢复原值,T2读到的数据就与数据库中的数据不一致。
并发控制的基本方法
并发控制的基本方法有排他锁和共享锁。
排他锁的定义:若事务T对数据对象A加上X锁,则只允许事务T读取和修改A。事务T释放A上的锁之前:其他事务不能读取和修改A,不能再对A 加任何类型的锁。
共享锁的定义:若事务T对数据对象A加上S锁,则事务T可以读取A,但不能修改A。事务T释放A上的S锁之前: 其他事务可以读取A,可以对A加S锁,但不能修改A,也不能对A加X锁
封锁协议
封锁协议有三级,分别叫一级封锁协议、二级封锁协议、三级封锁协议。
- 一级封锁协议:事务T在修改数据R之前必须先对其加X锁,直到事务结束才释放。
- 二级封锁协议:事务T在修改数据R之前必须先对其加锁(一级封锁协议),并且其他事务在取数据之前必须先对其加S锁,读完后即可释放S锁。
- 三级封锁协议:事务T在修改数据R之前必须先对其加锁(一级封锁协议),并且其他事务在读取数据之前必须先对其加S锁,直到事务结束才释放(二级封锁协议是读完就能释放)
活锁和死锁
活锁
活锁:事务T1封锁了数据R,事务T2又请求封锁R,于是T2 等待;T3也请求封锁R,当T1释放了R上的封锁之后系统首先批准了 T3 的请求,T2 仍然等待,T4 又请求封锁R,当T3释放了R上的封锁之后系统又批准了T4 的请求.......T2 有可能永远等待,产生活锁。
避免活锁的方法:先来先服务策略
死锁
这里的死锁和操作系统当中的死锁不一样。这里的死锁是事务T1 封锁了数据R1,T2 封锁了数据 R2,T1 又请求封锁R2,因T2 已封锁了 R2,于是T1 等待T2释放R2上的锁,接着T2 又申请封锁 R1,因T1 已封锁了 R1,T2 也只能等待T1,释放R1 上的锁,这样T1在等待T2,而T2又在等待T1,T1和T2两个事务永远不能结束,形成死锁。
死锁的预防
- 一次封锁法:每个事务必须一次将所有要使用的数据全部加锁,否则就不能继续执行。
- 顺序封锁法:预先对数据对象规定一个封锁顺序,所有事务按这个顺序实施封锁。
死锁的诊断与解除
诊断:如果一个事务的等待时间超过了规定的时限,就认为发生了死锁或构建事务等待图存在回路。
解除:选择一个处理死锁代价最小的事务,将其撤销(UNDO),释放此事务持有的所有的锁。
可串行化调度
定义:多个事务并发执行的结果=这些事务按某种次序串行执行的结果。
一个给定的并发调度,当且仅当它是可串行化的,才认为是正确调度。例如现有事务 T1 和 T2,若 T1与 T2 的并发执行结果与先T1后 T2 相同,或者与先 T2 后 T1 相同那么这个调度就是正确的,否则就是错误的。
冲突可串行化调度
冲突操作:指不同的事务对用一个数据的读写操作(读和写)和写写操作(写和写)。
不同事务的冲突操作和同一事物的两个操作是不能交换的,如果发生交换,自然会发生错误。基于此,如果调度能保证冲突操作的次序不变,就称为冲突可串行化的调度。冲突可串行化调度一定是可串行化调度。
结语
今天对并发控制的介绍就到这里。如果对您有帮助,希望您可以为我留下点赞和关注。谢谢您,这对我真的很重要!