SQLSERVER 快照隔离级别 到底怎么理解?

打印 上一主题 下一主题

主题 1014|帖子 1014|积分 3042

一:背景

1. 讲故事

上一篇写完 SQLSERVER 的四个事务隔离级别到底怎么理解? 之后,有朋友留言问什么时候可以把 snapshot 隔离级别给补上,这篇就来安排,快照隔离级别看起来很魔法,不过在修车之前,得先看下怎么开车。
二:snapshot 隔离详解

1. snapshot 之前的困境

在了解 snapshot 之前先看看没有它会存在什么样的困境?还是用上一篇的 post 表做案例,参考sql 如下。
  1. CREATE TABLE post(id INT IDENTITY,content char(3))
  2. GO
  3. INSERT INTO dbo.post VALUES('aaa')
  4. INSERT INTO dbo.post VALUES('bbb')
  5. INSERT INTO dbo.post VALUES('ccc');
  6. INSERT INTO dbo.post VALUES('ddd');
  7. INSERT INTO dbo.post VALUES('eee');
  8. INSERT INTO dbo.post VALUES('fff');
复制代码
大家都知道 SQLSERVER 的默认隔离级别是 READ COMMITTED,在下面的场景中 会话2 会被 会话1 阻塞。
  1. ---- 会话1 ----
  2. BEGIN TRAN
  3. UPDATE post SET content='zzz' WHERE id=1
  4. ---- 会话2 ----
  5. BEGIN TRAN
  6. SELECT * FROM post  WHERE id=1;
复制代码

那如何缓解呢?有一个粗暴的方法就是加 nolock 可以解决这个问题。
  1. BEGIN TRAN
  2. SELECT * FROM post (NOLOCK) WHERE id=1;
复制代码

但加上 nolock 也不是一种完美的解决方案,如果 会话1 在后续操作中 ROLLBACK 了,那对 会话2 来说就是脏读,那如何解决 既要....又要.... 的问题呢?这就引入了 snapshot 隔离级别,接下来看下怎么玩的。
2. snapshot 的简单使用

要想使用 snapshot 隔离级别,需要打开数据库的 ALLOW_SNAPSHOT_ISOLATION 开关,为了方便测试,我们把数据库 删除重建。
  1. DROP DATABASE MyTestDBCREATE DATABASE MyTestDBALTER DATABASE MyTestDB  SET ALLOW_SNAPSHOT_ISOLATION ONUSE MyTestDBCREATE TABLE post(id INT IDENTITY,content char(3))
  2. GO
  3. INSERT INTO dbo.post VALUES('aaa')
  4. INSERT INTO dbo.post VALUES('bbb')
  5. INSERT INTO dbo.post VALUES('ccc');
  6. INSERT INTO dbo.post VALUES('ddd');
  7. INSERT INTO dbo.post VALUES('eee');
  8. INSERT INTO dbo.post VALUES('fff');
复制代码
然后重新跑一下刚才的会话,在会话2的执行中设置快照隔离级别,参考 sql 如下:
  1. SET TRAN ISOLATION LEVEL SNAPSHOT
  2. BEGIN TRAN
  3. SELECT * FROM post  WHERE id=1;
复制代码


从图中看果然解决了 既要 .... 又要 的问题,既没有阻塞,也没有脏读,
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

飞不高

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表