2008年(239)
分类: Sybase
2008-06-17 23:23:09
我们前面已经提到,数据库系统的多个事务并发执行,带来了以下问题:丢失更新、存取未落实的数据、不可重复读、幻像读现象。对这些问题,需要通过并发控制机制来解决。锁机制,作为一种并发控制机制,使用两阶段封锁协议,来解决这些问题,其具体的处理方式如下:
(1)对丢失更新问题,锁机制要求:事务对数据的更新,必须申请排它锁,排它锁在事务提交后释放。
任何数据在被更新之前,必须要给它加排它锁;在数据更新完成、事务提交后,排它锁才会释放。由于排它锁之间互相排斥,数据一旦被一个事务加上排它锁,其他事务就不能获得该数据的排它锁,进而也不能更新数据。
正是数据排他性地访问,一个事务的更新不会覆盖另一个事务的更新,从而就不存在更新丢失的问题。使用锁机制,图6-1中的事务调度就改变为图6-6。
(2)对存取未落实的数据、不可重复读、幻像读现象,锁机制使用隔离级别来解决。
隔离级别的实现,就是给查询操作施加不同程度的共享锁。在SQL-92标准中,将隔离级别划分为四级。在不同的级别,查询操作所要求的锁、锁的持有时间不尽相同。级别越高,对锁的要求就越高,持有锁的时间也越长,相应地系统的并发处理能力就越低。用户可以根据自身的需要,选择应用系统的隔离级别。
这里需要说明的是,隔离级别实现的前提是:系统已经按照两阶段封锁协议,解决了更新丢失问题,即对数据的更新需要获得排它锁,排它锁在事务提交后释放。从以下对隔离级别的描述中,我们可以看出:隔离级别0和1,使用了严格两阶段封锁协议;而隔离级别2和3,使用了强两阶段封锁协议。在SQL-92标准中,数据库系统缺省的隔离级别为3。
1. 未落实的读(read uncommitted,0级)
在这一隔离级别,对数据的查询操作,不要求给数据加共享锁。
由于不需要加共享锁,系统的并发处理能力高,但同时事务能够读取未落实的数据,数据查询会出现不一致状况。事务的调度过程可见图6-7。
2. 落实的读(read committed,1级)
在这一隔离级别,对数据的查询操作,要求给数据加共享锁。在数据读取完成后,锁就释放,不需要等到事务完成。
由于查询操作需要对数据加共享锁,因此未落实、仍旧被排它锁锁定的数据,就不允许被读取。使用这一隔离级别,解决了并发事务之间未落实读的问题。事务的调度过程可见图6-8。
在这一隔离级别,查询操作申请的共享锁,在数据读取完成后立即释放。这时事务并没有完成,还要继续处理。如果该事务再次需要对同一数据进行读取,需要重新申请共享锁。由于共享锁只是在数据读取时才持有,因此事务对同一数据的多次读取,仍旧存在不可重复读问题,事务的调度过程可见图6-9。
该隔离级别既实现了数据读的一致性,又保证了事务之间的并发处理能力,因此许多数据库系统在缺省模式下,就使用此隔离级别。
3. 可重复读(repeatable read,2级)
在这一隔离级别,对数据的查询操作,要求给数据加共享锁。在数据读取完成后,锁不会被释放。一直到事务完成,事务申请的锁才全部释放。
由于被查询数据在事务运行过程中一直被加共享锁,其他的事务无法获取排它锁而更新该数据。因此,这一隔离级别解决了一个事务对同一数据多次读取而出现的不可重复读问题。事务的调度过程可见图6-10。
然而,这一隔离级别仍旧存在幻像问题。在事务运行时,其它的事务可以向表中插入新的记录,从而使该事务对同一区间数据的多次读取,而返回不同的结果。
4. 可串行读(serializable read,3级)
在这一隔离级别,对数据的查询操作,要求给数据加共享锁。在数据读取完成后,锁不会被释放。如果查询操作是基于数据的一个区间,就对整个区间加区间锁。一直到事务完成,事务申请的锁才全部释放。
如果一个事务执行基于数据区间的查询操作,并且获得了区间锁,那么该事务的执行过程中:
(1)任何其他事务往表中插入新的记录,如果该记录符合此数据区间,那么记录插入被拒绝。
(2)任何其他事务更改表中现有记录,如果更改后的记录符合此数据区间,那么记录更改被拒绝。
这一隔离级别解决了幻像读问题,但由于对数据的隔离要求很高,因此会严重地影响事务的并发处理。事务的调度过程可图6-11。