SQLSERVER 的四个事务隔离级别到底怎么理解?( 二 )


BEGIN TRAN SELECT * FROM dbo.post WITH(NOLOCK) WHERE id =3-- 脏读啦WAITFOR DELAY '00:00:05'SELECT * FROM dbo.post WITH(NOLOCK) WHERE id =3-- 正确的数据COMMIT

SQLSERVER 的四个事务隔离级别到底怎么理解?

文章插图
 
为了实现脏读这里加了 nolock 关键词,从图中明显的看到,获取的 zzzzz 数据是错误的,在一些和钱打交道的系统中是被严厉禁止的 。
有了这些基础再理解 可提交读 可能会容易些,是不是很好奇 SQLSERVER 是如何实现的呢? 参考 sql 如下:
SET TRAN ISOLATION LEVEL READ COMMITTEDGOBEGIN TRAN SELECT * FROM dbo.postWHERE id =3COMMIT
SQLSERVER 的四个事务隔离级别到底怎么理解?

文章插图
 
从加锁流程看,SQLSERVER 会逐一扫描数据页附加 IS 锁,扫完马上就释放,不像前面那样保持到 COMMIT 之后,如果找到记录所在的 Page 时,会对下面的所有记录附加 S 锁,这个时候 X 锁就进不来了,这就是它的实现原理,大家可以把刚才的 脏读 的sql中的 nolock 去掉试试看,两次读取结果都是一样的 。
4. READ UNCOMMITTED本质上来说 READ UNCOMMITTED 和 nolock 的效果是一样的,会引发脏读现象,主要是因为 READ UNCOMMITTED 根本就不会对表记录使用任何锁,参考sql如下:
SET TRAN ISOLATION LEVEL READ UNCOMMITTEDGOBEGIN TRAN SELECT * FROM dbo.postWHERE id =3COMMIT接下来观察 sqlprofile 的输出 。
SQLSERVER 的四个事务隔离级别到底怎么理解?

文章插图
 
可以看到 READ UNCOMMITTED 只会对表和堆表结构这种架构附加锁,不会对表中记录附加任何锁,也就会引发 脏读 现象 。
三:总结其实 SQLSERVER 还有带版本的 SNAPSHOT 隔离级别,在真实场景中往往会给 TempDB 造成很大的压力,这里就不介绍了 。
相信通过 Profile 观察到的加锁动态过程,会让大家有更深入的理解 。




推荐阅读