目录
前言
本文为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修改完毕,修改不会丢失。
二级封锁协议(解决修改丢失,脏读)
一有写操作就加X锁,并且一有读操作就加S锁,读完立刻释放S锁。
举例
原先采用一级封锁协议,T1写操作对数据对象C加X锁,T2读操作不加锁,是自由的,不需要获取锁就能读,就把T1撤回修改前的脏数据读走了。
现在采用二级封锁协议,T1写操作对数据对象C加X锁,T2读操作前对数据对象C加S锁。
xs锁互斥,T2就会进入等待状态,直到T1事务结束,释放锁,结束互斥状态,T2才能获得锁,而此时T1撤回完毕,T2所读数据就是T1撤回修改后的正确数据了。
三级封锁协议(解决修改丢失,脏读,不可重复读)
一有写操作就加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进行修改,事务结束,释放锁。
加锁产生问题
活锁
一个等待X锁的事务一直被新的等待X锁的事务插队而延后。
或者X锁一直被新的S锁延后。
死锁
持锁等待,T1持有T2想要的锁,T2有T1想要的锁,2者无限期等待。
解决办法
针对活锁
等待事务进入队列排队,依次获得锁。
缺点:维护这个队列代价挺高的。
针对死锁
一次封锁
把所有数据资源都加上锁。
缺点:降低了效率,也许有的操作可以并发执行。却被锁了。
顺序封锁
规定都是先获得锁1再拿锁2.但是难以实现。
缺点:实现起来很难,事务封锁请求是动态的很难排出顺序。
以上都是借鉴操作系统的方法。 不太适合数据库。
数据库更经常用:诊断-解除法
标签:封锁,事务,加锁,复习,修改,数据库,T2,T1,并发 From: https://www.cnblogs.com/lmj00/p/17845114.html