三级封锁协议的介绍

260 阅读6分钟

关于封锁协议

为啥会有封锁协议???

实际上是为了解决在并行操作中的几个问题

  • 丢失修改
  • 脏读
  • 不可重复读

一级封锁协议

  • 其对要修改的数据添加排他锁(X锁),让其他事务要对其进行修改的时候得等到当前事务的排他锁释放才能加排他锁从而进行修改
    • 其可以解决丢失修改,因为如果其他事务要对这个数据进行修改的时候只能等当前事务结束
      • 但是这也会导致后面的一个死锁问题,及A事务对数据1加了排他锁,在并行运行的时候,B事务对数据2加了排他锁,而事务A在运行到后面的时候发现要对数据二进行加排他锁,而此时数据二被事务B加了锁,所以事务A得等事务B与运行完毕,而此时事务B又要对数据1加排他锁,这是两给事务都出现问题了。
        • 有多种解决方法,但是有时候最好的还是随机回滚一个事务,以确保另一个事务能够正常运行
    • 这避免不了脏读和不可重复读
      • 即使数据1被事务A加了排他锁,事务B只要不对数据1进行修改,依然可以读取数据1,即使数据1有问题,也不会影响事务B对数据1的读取权限,所以一级封锁协议不会影响其他事务对已加排他锁的数据的读取,尽管是会出现问题的

        • 1_脏读
      • 不可重复读

        • 事务A在读取数据1的时候,事务B对数据1进行操作,导致事务A在读取数据1所进行操作的验算出现了问题
        • 1_不可重复读

二级封锁协议

  • 此处要求读取数据必须加共享锁,修改数据必须加排他锁,一旦加了排他锁就不能加共享锁,而加了共享锁,还可以加共享锁,不能加共享锁。此时可以在一级封锁协议的基础上避免了脏读,因为这个时候读取必须加共享锁,所以脏读直接被避免了
    • 一个数据在仅仅被读取的时候必须要加共享锁,读取完就会被释放。某个数据一旦加了排他锁就不能加共享锁,所以在一个数据正在被其他事务修改的时候,其不能被另外的事务加共享锁
    • 尽管避免了脏读,但是不可重复读还是没有被避免
      • 2_不可重复读

三级封锁

  • 在二级封锁协议的基础上延长了共享锁的时间,让其只有在事务结束的时候才会被释放,所以避免了如果当前事务A在读取数据1的时候,其他事务对数据1进行修改所带来的不可重复读的问题,其他事务只有对加了共享锁的数据加共享锁的权利,没有对其加排他锁的权利,如果要加排他锁,只能等当前事务结束,按照一个相对应的执行顺序来进行加锁 较完美的解决方案

活锁

  • 某个事物可能一直在等待其他事务释放它需要的数据,尽管某个事物最先开始等待,但是有可能是其他事务先都得对其加锁的权限,这就涉及到具体的数据库软件相关的标准了
    • 只要这个事务不会无限等待下去,就可以判断不会产生活锁 活锁问题
  • 使用队列来进行操作,采取先来先到的顺序,先入队的先出队,让其尽快获得数据1的使用权,这个得涉及到具体的功能实现,这里只给出理论上的方法(按照队列是可行的),具体情况下,不同的数据库的解决方法不同 解决方法

死锁

  • 发生了相互纠缠的问题就代表出现了死锁 死锁问题

死锁的预防

  • 一次封锁法
    • 一次就把这个事务所需要的所有数据都进行上锁操作
  • 顺序封锁法
    • 按照相对应的顺序进行上锁,
  • 这两个操作都会降低事务的并发性

死锁的判断

  • 根据每个事物的时间进行判断,但是会出现一个时间设置的问题,设置的好就会提高效率,一旦不合理就会出现各种问题
  • 画图,看事务之间的执行是否会出现闭环的情况,一旦出现就代表就会出现死锁
    • 根据各种事务之间的依赖关系来进行画图,一旦形成闭合回路(圆圈) 就代表着圈中事务之间会造成死锁

    • 等待图

死锁的解决方法

  • 按照日志文件去比较陷入死锁的几个事务之间的执行次数,释放执行最少的,以此来达到目的
  • 大多数情况都是直接回滚一个事务好让另一个事务可以达到目的,尽管具有随机性,但是避免了过多的计算,更简单

可串行化

  • 只要几个事务的并行执行的结果与某一次这几个事务的串行化结果相同,即称这个调度是可串行化的

冲突可串行化

  • 冲突可串行化比可串行化的要求更加严格

    • 交换两个不冲突的语句能达到可串行的要求,那么就代表这个调度是冲突可串行化的
  • 那什么是冲突的语句捏?

    • 同一数据的写写,读写之间都会出现问题,这个顺序一旦交换结果就不一样了(可以用这个来判断,即顺序一旦交换结果就不同即为冲突语句)
      • 不同事务对同一事务进行操作其顺序不同结果不同
      • 同一事务的两个操作
  • 可串行化不一定可冲突串行化,可冲突串行化一定可串行化

如果当前调度是可串行化调度,那么这个调度是正确的
  • 只要它可串行化就一定是正确的
    • 只要当前并行化的结果等于某个串行化的结果,就代表这个调度是正确的

两段锁协议

  • 指所有事务必须分两个阶段对数据项加锁和解锁

    • 在对该数据进行操作之前,一定要获得对该数据的封锁,在释放封锁之后该事物就不能申请和获得其他任何数据的封锁
    • 两个阶段,第一个是拓展阶段,第二个是收缩阶段
      • 事务可以申请获得任何数据项上的任何类型的锁,但是不能释放任何锁
      • 事务可以释放任何数据项上的任何类型的锁,但是不能再申请任何锁
    • 特别注意:两段锁协议不能避免死锁问题
  • PS:后面还有内容