事务并发调度之封锁技术
什么是事务
事务是数据库逻辑工作单位,是用户定义的一组操作序列。具有原子性、一致性、隔离性和持续性。原子性表示操作不可分割,要么都做,要么都不做。一致性表示数据库从一个一致性状态变换到另一个一致性状态隔离性表示事务执行过程中不被其它事务打扰持续性表示事务一旦提交,它对数据库中数据的改变就应该是永久性的。
事务并发的问题
(1) 丢失修改,当事务1在t1时刻读取A=16,事务2在t2时刻读取A=16,在t3时刻事务1修改A=A-1;写回数据库A=15。在t4时刻事务2更新A=A-1,写回数据库A=15。这样导致了事务1的修改丢失。如下图:
(2) 不可重复读,当事务1在t1时刻读取A=50,读取B=100,求和=150,事务2在t2时刻更新B=100,修改B=B*2,写回B=200,在t3时刻事务1读取值校对重读B,发现B变为200与第一次读取不一致,如下图:
(3) 脏读,事务1在t1时刻读取C=100,更新C=C*2写回数据库C=200,事务2在t2时刻读取C=200,在t3时刻事务1执行了更新C的回滚操作,C=100,那么此时就导致事务2读取的C为脏数据。如下图:
产生以上问题的原因:由于事务的并发破坏了事务的隔离性,导致各个事务并发出现干扰,要想是事务能达到隔离特性,就需要串行调度,也就是某一时刻只能有一个事务完成,其它事务等待。
封锁解决并发问题
封锁:是事务T在对某个数据操作时,例如,对表、记录等操作之前,先向系统发出请求,对其加锁,加锁后事务T就对该数据拥有了一定的控制,在事务T没有释放它的锁之前,其它事务不能更新该数据
封锁类型:排它锁(exclusive lock)也成为X锁,共享锁(share lock)也成为S锁。其关系为:对数据加X锁后,其它事务不能加任何锁,对数据加S锁后,其它事务可以加S锁,但不能加X锁。
采用三级封锁协议解决事务并发产生的问题:
(1) 一级封锁协议,解决修改丢失问题。描述如下:当事务T在修改数据R之前必须先对其加X锁,直到事务结束。如图:
事务1在读取A进行修改之前先对A加X锁,当事务2再请求对A加X锁时被拒绝,只能等待事务1释放A上的锁。
(2) 二级封锁协议,解决修改丢失和脏读问题。描述如下:在一级封锁协议基础上,当事务读取数据R之前必须先对其加S锁,读完后释放S锁。如图:
事务1在对C修改之前先加X锁,修改后写回磁盘,事务2请求数据C,首先请求在C上加S锁,因为事务1加了S锁,事务2只能等待事务1释放X锁,当事务1由于某种原因回滚C=100,释放X锁后,事务2获取S锁,读取C=100,避免了脏读。
(3) 三级封锁协议,解决修改丢失,脏读,不可重复读。描述如下:在一级封锁协议基础上,当事务读取数据R时必须先加S锁,当整个事务读取结束后释放S锁。如下图:
事务1在读取A,B之前,先对A,B加S锁,这样当其它事务只能对A,B加S锁,而不能加X锁,因此其它事务只能查询而不能修改A,B。所以当事务2修改B申请为其加X锁时被拒绝,只能等待事务1释放S锁。由于事务1没有结束因此S锁被占用,事务2等待,此时当事务1再次校验B时,读取B=100,避免了不可重复读。