并发控制 concurrency control


统一提交给dbms的那么多任务,怎么控制他们不干扰 为什么要并发控制

三种数据不一致现象

  • 丢失修改

        a用户发出请求,读出x余额,减十块,写回去  
        同时    
        b用户发出请求,读出x余额,加一百块,写回去 
    
  • 脏读(未提交依赖)

        b比a稍微快一点点   
        a读了一个修改了之后但是还没提交的数据(脏的数据)  
        万一a没提交呢?万一人家突然崩了呢?全部roll back了呢?
    
  • 不可重复读

        a用户转账业务,将x里的余额转到z里的余额   
        b用户统计x,y,z的和,只读事务,本来和不会变,但是  
    
        没太懂   
    

那如何控制数据一致呢

可串行性和可恢复性

尽可能排队,但是排队的话,并行度差,后台浪费,前台用户体验感差
解决方案======>
如何判断打架不打架
标志的相容和相斥
打架的时候 ==> 等等
不打架的时候 ==> 并行

调度schedule

事务的执行顺序
串行调度serial -- 全部排队
非串行调度nonserial -- 可以交叉执行

锁和时间戳

时间戳不讲,不考,可以不看
锁是加载在数据项上的标志
锁的颗粒度有多大(是一列还是一行是一个表还是一个库)

锁的类型
  • 读/共享锁 shared lock

          我在上面加了这个锁的话,你也可以加   
          select...     
          发送了一个select,在要select的对象上加了一个读锁  
    
  • 写/排他/独占锁 exclusive lock

          我在上面加了这个锁之后,你啥锁也不能加  
          update delete...   
          发送了一个update delete...,在要update delete...的对象上加了一个写锁   
    

    读锁和读锁相容,读锁和写锁,写锁和写锁不想容 所有的锁都在commit之后才释放

    两段锁协议

    遵循两段锁协议的一定可串行,可避免3种不一致问题

         1.所有的读加共享锁,所有的写加排他锁  
         2.所有的事务能找到一个分割点,上面是加锁的过程,下面是解锁的过程   
           所有的加锁都在第一个解锁之前,第一个解锁之后就没有加锁了
    
严格的两段锁协议

原因在于解锁太早,如果在commit之前别人又用了我解锁之后的资源,结果最后我rollback了,别人也得cascading rollback,用户体验不好(给都给我了,还拿回去????)。不如直接先等会
===解决==>

严格的两段锁协议:所有锁的释放是在事务提交之后的

普通的两段锁和严格的两段锁协议的并发度谁高?

他们都可以保证数据一致性,但是普通...并发度更高

死锁

不管哪种两段锁协议,都可能发生死锁,并没有完全避免。

如何检测死锁?

超时法,有向图法 ==> dbms的事

如何应对死锁?

强行中断一个,让其中一个先执行,执行完了再执行另一个。 ==>dbms的事

如何预防死锁? ==> 我们的事

(项目组)约定事务封锁的顺序

    不要出现
    a:wait(A);wait(B);  
    b:wait(B);wait(A);
    的情况  

锁的颗粒度

最大的颗粒度 -- 库
库 > 表 > 行 > 数据项(一个单元格)

目前dbms只提供到 行 级别

results matching ""

    No results matching ""