数据库复习总结(并发控制一)

发布时间 2023-11-20 22:51:16作者: lmj625

前言

本文为JMU22级数据库原理考前复习而总结归纳,刨除了课本以及课堂上晦涩且长篇大论的文章,以尽量简洁易懂的语句来对知识点进行归纳。

关于文章末尾提到的“诊断-解除法”将在下一篇文章进行阐释。



3种并发异常

丢失修改(写写异常)

两事务同时读入一个数据,一个事务T1提交的修改覆盖了另一个事务T2提交的结果。导致T2的修改丢失。


不可重复读(包括幻读情况 读写异常)

事务T1读取,T2更新,T1无法重现前一次读取结果。

3种情况:

  • T1按某些条件读取数据,T2修改,T1再次按相同条件读取,得到不同结果。

    下面2个情况称为幻读:

  • T1按某些条件读取数据,T2删除,T1再次按相同条件读取,发现数据神秘消失了。

  • T1按某些条件读取数据,T2插入,T1再次按相同条件读取,发现多了一些记录。


脏读

T1修改数据写入磁盘,T2读,T1撤回到原先数据。T2读到的数据就是脏的。



为处理并发异常出现的机制--加锁

进行操作前,对数据对象(表,记录)加锁

  • 事务获得X锁可以对数据读和写。

  • 事务获得S锁可以只能读数据。

XX,XS锁相斥。相斥会让事务进入等待锁释放的状态。
SS相容。

不加锁自由,与任何锁相容。



加锁规范--封锁协议

一级封锁协议(解决修改丢失)

一有写操作就加X锁,整个事务结束才释放。

举例

原先是不会加任何锁,就导致T1和T2同时修改一个数据对象,导致T1的修改丢失。
采用一级封锁协议之后,因为事务需要进行写操作,所以2个事务就在事务执行前对数据对象A加上X锁,T1获取到锁,进行操作,X锁和X锁互斥,T2就会进入等待状态,直到T1事务结束,释放锁,结束互斥状态,T2才能获得锁,而此时T1修改完毕,修改不会丢失。
image


二级封锁协议(解决修改丢失,脏读)

一有写操作就加X锁,并且一有读操作就加S锁,读完立刻释放S锁。

举例

原先采用一级封锁协议,T1写操作对数据对象C加X锁,T2读操作不加锁,是自由的,不需要获取锁就能读,就把T1撤回修改前的脏数据读走了。
现在采用二级封锁协议,T1写操作对数据对象C加X锁,T2读操作前对数据对象C加S锁。
xs锁互斥,T2就会进入等待状态,直到T1事务结束,释放锁,结束互斥状态,T2才能获得锁,而此时T1撤回完毕,T2所读数据就是T1撤回修改后的正确数据了。
image


三级封锁协议(解决修改丢失,脏读,不可重复读)

一有写操作就加X锁,并且一有读操作就加S锁,整个事务结束一起释放XS锁。

举例

原先采用二级封锁协议,T1读操作对数据对象A和B都加S锁,T2写操作对数据对象B加X锁,XS锁互斥,T2开始等待。T1读取完,立刻释放锁,T2获取到锁,T1求完和又要读操作,再次对数据对象A和B都加S锁。与T2的X锁相斥,待T2修改完B,释放锁。再次读取数据求和,两次求和结果不同,无法进行验算操作。

现在采用三级封锁协议,T1读操作对数据对象A和B都加S锁,T2写操作对数据对象B加X锁,XS锁互斥,T2开始等待。T1读取完,不释放锁,继续T1事务里的操作,即再次求和以进行验算,验算完毕,事务结束,释放所有锁,T2结束等待获得X锁,对B进行修改,事务结束,释放锁。
image



加锁产生问题

活锁

一个等待X锁的事务一直被新的等待X锁的事务插队而延后。

或者X锁一直被新的S锁延后。


死锁

持锁等待,T1持有T2想要的锁,T2有T1想要的锁,2者无限期等待。



解决办法

针对活锁

等待事务进入队列排队,依次获得锁。

缺点:维护这个队列代价挺高的。


针对死锁

一次封锁

把所有数据资源都加上锁。

缺点:降低了效率,也许有的操作可以并发执行。却被锁了。


顺序封锁

规定都是先获得锁1再拿锁2.但是难以实现。

缺点:实现起来很难,事务封锁请求是动态的很难排出顺序。


以上都是借鉴操作系统的方法。 不太适合数据库。

数据库更经常用:诊断-解除法