“可串行化”是ANSI SQL中定义的最高事物隔离级别。运行在这种隔离级别下的事物不会发生”脏读”、”不可重复读”以及”幻像读”,事物可以重复多次执行相同查询,并且每次都能够得到完全相同的结果。在这种隔离级别下,其它事物不能插入任何将出现在结果集中的记录行。ASE是如何实现的呢,我们结合例子加以说明。让我们看一个例子,假设事物TA执行如下操作:
       begin transaction
         …..
         –第一次读取
         select count(*) from accounts where balance>=1000 and balance <=3000 
        …..
         –第二次读取
         select count(*) from accounts where balance>=1000 and balance <=3000
         ….
       commit

    事物TA在第1次执行查询时得到账户余额在1000和3000之间的账户数假设为5;当它第2次执行相同查询语句之前,事物TB执行了如下语句:
     begin transaction
       ……
       insert into accounts(actno, balance) values (‘2222222’,2000)
     commit

    假设TB执行的insert语句在事物TA第一次查询完成之后,第二次执行开始之前运行;TA和TB都是非链式模式,TA运行在隔离级别3下,TB运行在隔离级别1下,表accounts采用”datarows”锁定机制。
  
    由于事物TA运行在隔离级别3下,当执行头一个select语句时由于balance字段上有可用索引,ASE会对查询命中的(即满足查询条件的)记录行加”共享行级范围锁(range locks)“,即”Sh_row range locks”;如果没有可用索引的话,ASE会加”共享表级范围锁“,即 “Sh_table range lock”。下面分两种情况描述:
    (1) 如果accounts表中已有数据中没有balance> 3000的记录,那么ASE还会加一个”无限键锁(Infinity key lock)“,对于本示例就是”Sh_row  Inf  key”锁。当事物TB执行insert语句插入balance=2000的新记录,ASE需要获得排它行锁(Ex_row),由于TA事物持有”Sh_row  Inf  key”锁,因此TB的排它锁请求不能成功,将被阻塞,直到TA事物释放了”Sh_row  Inf  key”锁。这样一来,事物TA第二次执行相同的查询时,得到满足相应条件的账户的个数是与第一次是相一致的,不会产生”幻像读”。
    (2) 如果accounts表中已有数据中具有balance> 3000的记录,那么ASE还会在满足balance>3000的记录集合中选择余额最小的那条记录上也加一个”共享行级范围锁”,即”Sh_row range lock”,这个锁又叫做”下一键锁(next-key lock)“。当事物TB执行insert语句插入balance=2000的新记录,ASE需要获得排它行锁(Ex_row),由于TA事物持有”next-key lock”锁,因此TB的排它锁请求不能成功,被阻塞,直到TA事物释放了”netxt-key lock锁。这样一来,事物TA第二次执行相同的查询时,得到满足相应条件的账户的个数是与第一次是相一致的,不会产生”幻像读”。

   通过上面的示例,我们可以看到,ASE使用”范围锁”、”无限键锁”或”下一键锁”来防止”幻像读”,实现隔离级别3所规定的语义的

   范围锁可以是共享锁、更新锁或排它锁,根据锁定方案的不同,它们要么是行锁,要么是页锁。对于范围锁,ASE 系统存储过程sp_lock 输出的 context 列中会显示”Range”。对于无限键锁, sp_lock 在不存在的记录行(实际上是根索引页的行 0)上显示一个锁,并在 context 列中显示”Inf key”。

To report this post you need to login first.

Be the first to leave a comment

You must be Logged on to comment or reply to a post.

Leave a Reply