Username: Password:

SQL Server的隔离模式和锁深入分析(一)-数据库专栏,SQL Server
来源:作者: 发布时间:2007-12-25 13:48:16

最近在论坛上,看到很多sql server的锁定模式和工作原理的讨论。看来有必要总结一下。

      sql server有4中隔离模式,和多种锁。我就简单地整理一下心得体会,如有错误,敬请指正。

前言     

      隔离模式和锁有差别,大家千万不要搞混。隔离模式是规范了并发控制行为,而锁是控制锁定的粒度。但是两者都会对您应用系统的并发法产生重大影响。缺省是read committed隔离模式和行级锁(rowlock)。

      不同数据库间,在这方面,有很多差别,也有一起的地方。这些表面现象其实在于体系架构上的差别。

      需要指出的一点是:我们不要去判断这种差别孰优孰劣的问题,因为不同数据库产品都有自己的指标。尤其用编程上的方便来判断是很幼稚的。作为应用系统,应该是在编程研发上应该去适应数据库,而不是让数据库来适应编程研发。因为数据库的选型方案是更本不会考虑编程的方便和否。很多业务逻辑控制问题应该在系统设计上考虑,不能只依靠数据库系统的锁定机制来解决您应用系统的逻辑问题。

  read committed模式

       这是sql server缺省,也是大家最常用的一种。也是很多用过oracle人感觉不适应的地方。

      example:

      session 1  

      begin tran

      insert into t1 values(1,allan)

      session 2

      select * from t1

      嗯?怎么回事,被挂住了。oracle中可不会,我看不到1,allan的这条记录不就好了。

      其实这就是oracle和sql server在这一点上的差别。oracle采用了rollback的机制,确保了在read committed模式下行记录锁定不会影响其他事务的读取(更新还是会被lock住的)。因此,oracle提供了更强的并发度。显然,sql server简化了这个架构,自然就只能这样了。

      sql server在read committed模式下,一个事物的查询语句是不会忽略其他事务未提交的数据(假如您的查询条件包括了其他事务为提交的数据),sql server将让您等待其他提交,从而确保数据一致性,显然并发度比oracle低。假如出现了等待情况,大家能够根据这个标准来判断。

      但是,两个事务同时更新一条记录或插入主键相同的记录的话,都会有一个等待,sql server和oracle都是这样的。

      那么下面让我用例子来仔细说明一下:

      测试表如下:
     
测试表如下:
c1 c2 c3
----------- --------------------- --------------------
1 200.5000 hellen
2 129.1400 hellen
3 288.9700 allan

session 1:

begin transaction

delete from test where c1=1



session 2:
select * from test
此时被挂住,因为包括了c1=1的记录,sql server当然需要您等待。

假如我不选c1=1的记录呢,自然就不会被waitting了。
session3:
select * from test where c1=2
select * from test where c1=3

c1 c2 c3
----------- --------------------- --------------------
2 129.1400 hellen

(所影响的行数为 1 行)

c1 c2 c3
----------- --------------------- --------------------
3 288.9700 allan

(所影响的行数为 1 行)



没有被挂起,一切很好。


此时,还能够发现一个很有趣,很容易迷惑您的现象。
session 4
select * from test where c1<>1
结果也被挂住了,似乎rowlock出了“问题”?不要急,原来由于我这个表test建了主键(c1字段)。我认为这是由于update,delete操作引起了索引上行的lock。
而此时,假如执行select * from test where c1>1是没有问题的。

那么,我们只要强制跳过聚集索引的索引页和索引叶节点页(数据页)中行锁定的部分。
select * from test with(fastfirstrow) where c1<>1
果然就一切ok。
因此,对于很多现象,我们需要进一步地去思考和去解迷。


下面,我们通过sp_lock查看来在说明一下

通过sp_lock查看:
spid dbid objid indid type resource mode status
------ ------ ----------- ------ ---- ---------------- -------- ------ ------------------------------------
53 7 789577851 1 pag 1:126 ix grant
53 7 789577851 1 key (010086470766) x grant
53 7 789577851 1 pag 1:127 ix grant
53 7 789577851 2 key (090041892960) x grant
53 7 789577851 0 tab ix grant

(1)  id 789577851就是表test,能够查询sysobjects。
(2) 关于tab的ix,是表结构的意向排他锁 。此时,假如您执行alter table命令来改变表结构(会对表结构上x锁)是会被挂住  的。
(3) pag是页锁,就是索引页锁,此时为什么会有两个呢?显然1:126是索引树的中间页节点页面,而1:127是叶节点页,也就是数据页(聚集索引的表存储结构)。因此,任何对索引页上x锁的操作都会被挂住,而上ix,s不会,sql server会进一步判断行级锁。此时,能够通过select * from test with(paglock) where c2=2测试。
(4) key (010086470766) ,key (090041892960) 的两个x最明显了,就是行级独占锁。一个是索引中间页上的行级锁,一个是叶节点(数据页)上的行级锁。

这就是sql server最常用的read committed隔离模式的情况,下次继续讨论read uncommitted隔离模式。

喜欢本文,那就收藏到:

    Del.icio.us Google书签 Digg Live Bookmark Technorati Furl Yahoo书签 Facebook 百度搜藏 新浪ViVi 365Key网摘 天极网摘 和讯网摘 博拉网 POCO网摘 添加到饭否 QQ书签 Digbuzz我挖网
相关评论  我也要评论
还没有关于此文章的相关评论!
  • 昵称: (为空则显示guest)
  • 评论分数: ★ ★ ★★★ ★★★★ ★★★★★
  • 评论内容:(不能超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规。
  • 导航
    赞助商
    文章类别
    订阅