2008年12月21日星期日

SQL Server2005数据库事务隔离级别实验记录(2)--Read Committed

Read Committed:SQL 默认级别,读取时设置共享锁,避免其他进程脏读。
实验:初始状态:Ntusername ='1' where rownumber =8

Part I:------------------------------------------------------------------
在默认隔离级别下,执行下面语句(52)进程
begin transaction
update t08102101
set Ntusername ='2'
where rownumber =8
select @@trancount

sp_lock看到的锁信息如下:
52 5 1582628681 1 KEY (08000c080f1b) X GRANT
52 5 1582628681 0 TAB IX GRANT
52 5 1582628681 1 PAG 1:333532 IX GRANT

然后执行下面的语句,(65)进程
set transaction isolation level read committed
select * from t08102101
where rownumber =8
无法完成查询,取不到任何数据,锁信息如下:
52 5 1582628681 1 KEY (08000c080f1b) X GRANT
52 5 1582628681 0 TAB IX GRANT
52 5 1582628681 1 PAG 1:333532 IX GRANT

65 5 1582628681 1 KEY (08000c080f1b) S WAIT
65 5 1582628681 0 TAB IS GRANT
65 5 1582628681 1 PAG 1:333532 IS GRANT

此时执行

select * from t08102101 (nolock)
where rownumber =8

可以得到 Ntusername ='2' where rownumber =8的结果,锁信息没有变化

而在52进程执行
select * from t08102101
where rownumber =8
结果是Ntusername ='2' where rownumber =8

Part II:------------------------------------------------------------------
回滚之前的更新操作,打开read_committed_snapshot开关:
alter database dbcenter
set read_committed_snapshot on

再次执行
begin transaction
update t08102101
set Ntusername ='2'
where rownumber =8
select @@trancount

锁信息如下

52 5 1582628681 1 KEY (08000c080f1b) X GRANT
52 5 1582628681 0 TAB IX GRANT
52 5 1582628681 1 PAG 1:333532 IX GRANT

执行下面的语句,(65)进程
set transaction isolation level read committed
select * from t08102101
where rownumber =8

可以得到Ntusername ='1' where rownumber =8的更新前结果

在另外进程执行(nolock)查询,得到Ntusername ='2' where rownumber =8

此时,sp_lock看到的只有52进程的排他锁信息。

而在52进程中执行
set transaction isolation level read committed
select * from t08102101
where rownumber =8
得到的是Ntusername ='2' where rownumber =8

结论:数据库默认的事务隔离级别是read committed,且该级别不允许读取未提交中的数据

--13:23 2008-12-21