Skip to Content
Author's profile photo Former Member

ASE不同隔离级的基本原理——”可重复读”隔离级(2)

    运行在隔离级别2(Repeatable Read))下的事物不会发生”脏读”和”不可重复读”问题。下面将结合一些例子讲述ASE实现该隔离级别的基本原理。让我们看一个例子,假设事物TA执行如下操作:
    begin transaction
        …..
        select balance from accounts where actno=’1234567′   –第一次读取
        …..
        select balance from accounts where actno=’1234567′  –第二次读取
    commit

   事物TA在第1次执行查询时得到账号’1234567’的余额假设是1000;在其第2次执行相同查询语句之前,事物TB执行如下语句:
    begin transaction
        ……
        update accounts set balance=balance+100 where actno=’1234567′
    commit

   假设TA中的第一次读取先执行,在它执行完后、第二次读取执行之前,TB中的update语句执行。TA和TB都是非链式模式,TA运行在隔离级别2下,TB运行在隔离级别1下,表accounts采用”datarows”锁定机制。
    由于事物TA运行在隔离级别2下,当执行头一个select语句时,ASE会对actno=’1234567′ 对应的记录行加”共享行锁(Sh_row)”,此外还会加”共享意向锁”,因为account表加了”共享行锁”(注意:在隔离级别1下,对于这个select语句是不会加共享行锁的,因此也就不会加共享意向锁)。当事物TB执行update语句更新actno=’1234567’对应的数据行时需要加”排它行锁(Ex_row)”,但TA已经在这条记录上持有”共享行锁”,因此TB发出的”排它行锁”请求不能成功,被”阻塞”。TB中的update语句由于”阻塞”而不能执行,直到事物TA释放了所持有的”共享行锁”。因此,事物TA读取的数据就不会被TB修改。当TA事物第二次执行select查询时读到的数据也就与第一次读取到的数据保持一致,从而实现了隔离级别2所要求的可重复读。此外,如果TB事物中执行的update语句替换为delete accounts where actno=’1234567’语句,delete语句同样也需要请求”排他行锁”,因此道理是一样的。

   需要注意的是:ASE隔离级别2只支持”数据行锁定(datarows locking)”或”数据页(datapages locking)”表。
   
   概念解释:意向锁 (Intent lock) 。意向锁指示某个表上当前持有行级锁(或页级锁)。ASE会对每个有共享行(或页)锁或排它行(或页)锁的表应用一个意向锁。一个连接上运行的事物,不管表上有多少个行锁或页锁,该表上只有一个意向锁。意向锁可以是”排它意向锁”,也可以是”共享意向锁”。
设置”意向锁”可阻止其它事务在包含有”行级锁”或”页级锁”的表上获取有冲突的”表级锁”。只要行锁或页锁对事务有效,就会持有意向锁。

   此外,在隔离级别2(或3)下,如果select查询使用noholdlock选项的话,那么在事物中这个语句执行完后不会加共享锁,但是带有noholdlock的select查询在执行期间,如果命中的记录上有”排它行锁”,那么一样会阻塞。我们看一个例子,假如accounts表采用Datarows锁定,事物运行在非链式模式、隔离级别1下:
     begin tran
        …
        select * from accounts noholdlock where balance < 4000
        …
     commit
     select语句执行完后,通过sp_lock查看,这个语句没有保持共享行锁。

Assigned Tags

      Be the first to leave a comment
      You must be Logged on to comment or reply to a post.