数据库 __ 基于锁的协议的并发控制

2022/6/13 2:20:26

本文主要是介绍数据库 __ 基于锁的协议的并发控制,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

确保隔离性的方法之一是要求对数据项以互斥的方式进行访问;换句话说,当一个事务访问某个数据项时, 其他任何事务都不能修改该数据项。 实现该需求最常用的方法是只允许事务访问当前该事务持有锁( lock ) 的数据项。

锁就是指:只有获得相应的锁后,才能执行相应的操作。
一个事务只要还在访问数据项,它就必须拥有该数据项上的锁。

我们将锁分为两类:

  1. 共享锁( 记为S ):当事务获得了排他锁,则可以在该数据项进行操作。
    许多事务可以同时持有一个数据项上的共享锁。
  2. 排他锁( 记为X ):当事务获得了排他锁,则在该数据项既可读又可写
    只有当其他事务在一个数据项上不持有任何锁( 无论共享锁或排他锁)时,一个事务才允许待有该数据项上的排他锁。

关于锁的几个基本操作:

  1. 每个事务都要根据自已将对数据项Q进行的操作类型申请适当的锁。
    具体来说:一个事务通过执行lock-S ( Q ) 指令来申请数据项Q 上的共享锁。类似地,一个事务通过执行lock-X (Q) 指令来申请排他锁。

  2. 该事务将请求发送给并发控制管理器。事务只有在并发控制管理器授予所需锁后,才能继续其操作。
    锁的授予必然是在事务申请锁操作与事务的下一动作的间隔内。在此期间内授权加锁即可,准确时间并不重要

  3. 因此如果该数据项已被另一事务加上了不相容类型的锁,则在所有其他事务持有的不相容类型锁被释放之前, 并发控制管理器不会授予锁,事务只好等待,直到所有其他事务持有的不相容类型锁被释放。
    尽管数据项Q 上存在B 类型锁,如果事务T,可以立即获得数据项Q 上的锁,则我们就说A 类型锁与B 类型锁是相容的(compatible) 。
    这样的一个函数可以通过矩阵方便地表示出来。
    image
    当且仅当类型A 与类型B 是相容的,该矩阵的一个元素comp (A, B ) 具有true 值。

容易得到只有共享型与共享型是相容的,其余都不相容。

两阶段封锁协议

封锁协议: 规定事务何时对数据项们进行加锁、解锁的一组规则。封锁协议限制了可能的调度数目。

常用的保证可串行性的一个协议是两阶段封锁协议。

两段锁协议::要求每个事务分两个阶段提出加锁和解锁申请。

  1. 增长阶段:事务可以获得锁,但不能释放锁。
  2. 缩减阶段:事务可以释放锁,但不能获得新锁。
    一旦该事务释放了锁,就不能再发出加锁请求。

锁转换:将一种类型的锁改为另一种类型。

  • 升级: 表示从共享到排他的转换,
  • 降级: 表示从排他到共享的转换。

锁转换不能随意进行,锁升级只能发生在增长阶段,而锁降级只能发生在缩减阶段。

封锁协议作用:

  1. 我们可以证明两阶段封锁协议保证冲突可串行化。
    事务的封锁点: 在调度中事务获得其最后加锁的位置(增长阶段结束点)。
    多个事务可以根据它们的封锁点进行排序,这个顺序就是事务的一个可串行化顺序。

  2. 遵循两阶段封锁也可能会发生死锁。

活锁和死锁

活锁

活锁的情形:
事务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两个事务永远不能结束,形成死锁

产生死锁的原因
两个或多个事务都已封锁了一些数据对象,然后又都请求对已为其他事务封锁的数据对象加锁,从而出现死等待。

解决死锁的方法

处理死锁问题有两种主要的方法。

  1. 预防死锁:保证系统永不进入死锁状态。
  2. 死锁恢复:我们允许系统进人死锁状态,然后试着用死锁检测与死锁恢复机制进行恢复。

两种方法均有可能引起事务回滚。
如果系统进入死锁状态的概率相对较高, 则通常使用死锁预防机制;否则,使用检测与恢复机
制会更有效。



这篇关于数据库 __ 基于锁的协议的并发控制的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程