-
并发操作带来的数据不一致性包括三类:丢失修改、不可重复读和读脏数据。
- 丢失修改
两个事务T1和T2读入同一数据并修改,T2提交的结果破坏了T1提交的结果破坏了(覆盖了)T1提交的结果,导致T1的修改被丢失。 - 不可重复读
事务2读取了数据R,当事务1读取对数据R进行修改,然后事务2再读取数据(希望与第一次读取的是相同的值)时,得到的数据与前一次不一样,这是由于第一次读取数据后,事务1做了修改,导致前后不一样。 - 读脏数据
当事务1修改了某个数据后,事务2读取了数据,然后事务1背叛了事务2,放弃了修改,然后事务2就gg。
- 丢失修改
-
共享锁
又称为读锁,s锁
若事务T对数据对象A加上S锁,则事务T只能读A,其他事务只能再对A加S锁,不能加X锁,知道T释放A上的S锁,这就保证了其他事务可以读A,但在T释放A上的S锁之前不能对A做任何修改
-
排他锁
又称写锁,X锁
若事务T对数据对象A加上 X锁,则只允许T读取和修改A,其他任何事务都不能再对A加任何类型的锁,直到T释放A上的锁。
-
封锁协议
- 一级封锁协议
事务t在修改数据R之前必须先对其加x锁,知道事务结束菜释放,事务结束包括正常结束(commit)和非正常结束(rollback)
可以防止丢失修改。保证事务t的可恢复。 - 二级封锁协议
一级封锁协议加上事务t在读数据R之前必须先对其加S锁,读完后方可释放。
可以进一步保证不读脏数据 - 三级封锁协议
一级封锁协议加上事务T在读取数据R之前必须先对其加S锁,直到事务结束才释放。
可以防止不可重复。
- 一级封锁协议
-
活锁
事务1封锁了数据R,事务2请求封锁数据R,事务3请求封锁数据R,最后事务1,结束了,事务3得逞了。事务2就是被活锁了。
只要保证先申请先服务的原则就可以避免。
-
死锁
死锁 如果事务T1封锁了数据R1,T2封锁了数据R2,然后T1又请求封锁R2,因T2已封锁了R2,于是T1等待T2释放R2上的锁。接着T2又申请封锁R1,因T1已封锁了R1,T2也只能等待T1释放R1上的锁。这样就出现了T1在等待T2,而T2又在等待T1的局面,T1和T2两个事务永远不能结束,形成死锁。