并发控制 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只提供到 行 级别