一:背景

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 MyTestDB
  2. CREATE DATABASE MyTestDB
  3. ALTER DATABASE MyTestDB SET ALLOW_SNAPSHOT_ISOLATION ON
  4. USE MyTestDB
  5. CREATE TABLE post(id INT IDENTITY,content char(3))
  6. GO
  7. INSERT INTO dbo.post VALUES('aaa')
  8. INSERT INTO dbo.post VALUES('bbb')
  9. INSERT INTO dbo.post VALUES('ccc');
  10. INSERT INTO dbo.post VALUES('ddd');
  11. INSERT INTO dbo.post VALUES('eee');
  12. INSERT INTO dbo.post VALUES('fff');

然后重新跑一下刚才的会话,在会话2的执行中设置快照隔离级别,参考 sql 如下:


  1. SET TRAN ISOLATION LEVEL SNAPSHOT
  2. BEGIN TRAN
  3. SELECT * FROM post WHERE id=1;

从图中看果然解决了 既要 .... 又要 的问题,既没有阻塞,也没有脏读,哈。。。

3. snapshot 是什么原理

要探究个明白得从底层的数据页说起了,可以用 DBCC PAGEDBCC PAGE 命令观察。


  1. DBCC TRACEON(3604)
  2. DBCC IND(MyTestDB,post,-1)
  3. DBCC PAGE(MyTestDB,1,240,3)

从图中可以看到,数据页上每一个 Slot 指向的表记录尾部会有一些空间来存储 Version Information 记录的版本信息,比如上面的 事务号时间戳,版本指针,目前看 Version Pointer: Null 指向的是 NULL,有了这些基础之后,重新将刚才的两个会话开启再次观察 240号 数据页。

从图中可以清晰的看到,会话1已经将内存页修改成了 zzz,会话2 读取的 aaa 肯定就是 3:8:0 指向的版本记录了。

有些朋友可能就有疑问了,这个 3:8:0 是怎么看出来的?其实就是记录中的 00000800 00000300 这一段,看不习惯的话可以用 windbg 附加一下。

接下来的一个问题是 3:8:0 到底指向的是哪里?如果看过 MSDN 上的说明应该知道它指向的是 TempDB 数据库,接下来用 DBCC PAGE 去看下是不是我的 aaa 记录。


  1. DBCC PAGE(tempdb,3,8,2)

输出结果如下:


  1. PAGE: (3:8)
  2. Memory Dump @0x000000203ABF8000
  3. 000000203ABF8000: 01020000 2000fe00 00000000 00000100 00000000 .... ...............
  4. 000000203ABF8014: 00000100 07000080 451fb900 08000000 03000000 ........E...........
  5. 000000203ABF8028: 25000000 78010000 50000000 00000000 00000000 %...x...P...........
  6. 000000203ABF803C: 00000000 01000000 00000000 00000000 00000000 ....................
  7. 000000203ABF8050: 00000000 00000000 00000000 00000000 26010059 ................&..Y
  8. 000000203ABF8064: 0000008b 03000000 00010000 00000000 00050000 ....................
  9. 000000203ABF8078: 00000000 00000050 00000000 010b0000 00220000 .......P........."..
  10. 000000203ABF808C: 00815c00 00000000 00000000 00140000 0050000b ..\..............P..
  11. 000000203ABF80A0: 00010000 00616161 02000000 00000000 00000080 .....aaa............
  12. 000000203ABF80B4: 03000000 00000000 00000000 381f0000 00000000 ............8.......
  13. ...
  14. 000000203ABF9FF4: 00000000 0b01d000 be006000 ..........`.
  15. OFFSET TABLE:
  16. Row - Offset
  17. 0 (0x0) - 96 (0x60)

从右边的asc码看果然就是我的 aaa,如果大家对整个流程有点懵的话,画个图大概就像下面这样。

快照级别事务 的存储原理有了一定的认识之后,接下来从锁的角度观察下为什么能避开阻塞,将二个会话重新执行下,用 SQL Profile 观察下加锁过程。

从图中可以看的非常清楚, 会话1在1:240:0 记录上获取到了 X 锁,会话2 压根就没在表记录上附加任何锁,直接提取表记录的 Version Pointer 指向的 Slot,完美避开 X 锁,也就不存在锁互斥啦。。。

三:总结

从储存机制和加锁过程可以看到如下特点:

  • 开启 ALLOW_SNAPSHOT_ISOLATION 之后,每条记录都会有一个 版本信息,浪费了大量的数据页空间。

  • tempdb 是一个极其宝贵的服务器级别共享空间,被所有的数据库共享,遇到高并发的情况下可能会引发大量的 闩锁 等待造成的语句阻塞,所以一定要慎用,尽可能的减轻 tempdb 的负担。

SQLSERVER 快照隔离级别 到底怎么理解?的更多相关文章

  1. 数据库的快照隔离级别(Snapshot Isolation)

    隔离级别定义事务处理数据读取操作的隔离程度,在SQL Server中,隔离级别只会影响读操作申请的共享锁(Shared Lock),而不会影响写操作申请的互斥锁(Exclusive Lock),隔离级 ...

  2. 转:数据库的快照隔离级别(Snapshot Isolation)

    数据库的快照隔离级别(Snapshot Isolation)   隔离级别定义事务处理数据读取操作的隔离程度,在SQL Server中,隔离级别只会影响读操作申请的共享锁(Shared Lock),而 ...

  3. SQL Server 中的事务与事务隔离级别以及如何理解脏读, 未提交读,不可重复读和幻读产生的过程和原因

    原本打算写有关 SSIS Package 中的事务控制过程的,但是发现很多基本的概念还是需要有 SQL Server 事务和事务的隔离级别做基础铺垫.所以花了点时间,把 SQL Server 数据库中 ...

  4. SQLServer 事务隔离级别与锁的申请和释放

    脏读:当一个事务开始更新数据,但是这个事务并没有完全提交,这个时候第二个事务开始读取数据,把第一个事务所更改的数据读了出来, 第二个事务读取的数据时临时的,因为有可能第一个事务最终有可能做回滚操作 不 ...

  5. Sqlserver事务隔离级别详解

    sqlserver存储方式   页    sqlserver是以页的形式存储数据,每个数据页的大小为8KB,sqlserver会把空间分为多个页,sqlserver与数据交互单位最小的io操作就是页级 ...

  6. Mysql隔离级别 sql示例理解

    前言 事务要解决的是多线程并发修改数据库的问题.Mysql innodb 引擎支持事务.类似 Java 中的各种锁,例如乐观锁(CAS),读写锁,悲观锁.事务也有很多级别. 每个隔离级别要解决的问题都 ...

  7. spring事务的隔离级别(透彻理解)

    1.spring 事务这个东西,是轮子,每个service,都需要用到.所以干脆就做在框架层实现. 2.spring是怎么给你的service方法加事务的呢?jdk动态代理,会针对每个service类 ...

  8. sqlserver默认隔离级别下并发批量update同一张表引起的死锁

    提到死锁,最最常规的场景之一是Session1 以排它锁的方式锁定A表,请求B表,session2以排它锁的方式锁定B表,请求A表之类的,访问顺序不一致导致死锁的情况本文通过简化,测试这样一种稍显特殊 ...

  9. SqlServer——事务—隔离级别

    隔离实际上是通过锁来实现的,作用于整个事务,它通常在事务开始前指定,如 SET TRANSACTION ISOLATION LEVEL READ Committed,指定后面的事务为 已提交读:而锁是 ...

  10. SQLServer 事务隔离级别

    MSSQL 事务级别 分类: 数据库2012-12-28 11:17 1050人阅读 评论(0) 收藏 举报 事务 级别 等级优化数据库 一个系统项目做大了,就会遇到性能问题.数据库的优化将是解决性能 ...

随机推荐

  1. ES6 学习笔记(五)基本类型Boolean

    Boolean 1.需要注意的地方: 取值:true false 对于值为空字符串,0,-0,NaN,Null,undefined,false的布尔对象,它都会有一个初始值false.对于其它的值如& ...

  2. 高性能MySQL(第4版) 第一章 MySQL架构 读书笔记

    这本书去年11月出的,今年中文版也出了,并且直接上了微信读书,之后有空就读一读,分享下读书笔记~ 原文内容比较充实,建议有时间可以读一下原文. 第一章主要是个概览. MySQL的逻辑架构 默认情况下, ...

  3. 什么是CLR?

    CLR翻译为"公共语言运行库",全称是Common Language Runtime,它是一个可以由多种语言使用的"运行时",CLR的核心功能如内存管理,程序集 ...

  4. 决策树(二):后剪枝,连续值处理,数据加载器:DataLoader和模型评估

    在上一篇文章中,我们实现了树的构造,在下面的内容中,我们将中心放在以下几个方面 1.剪枝 2.连续值处理 3.数据加载器:DataLoader 4.模型评估 一,后剪枝 • 为什么剪枝  –" ...

  5. Day18.2:对象创建的内存分析图解

    对象创建的内存分析 我们从两块最常用的内存空间对对象创建进行内存分析 堆内存:存放的是对象的具体信息:在程序之中堆内存空间的开辟是通过new完成的 栈内存:存放的是对象的地址信息,即通过地址找到堆内存 ...

  6. 解决linux vlc设置中文问题

    解决方法 sudo apt install vlc-l10n

  7. jquery操作内容

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. 【Hadoop学习】上:组成介绍、生态体系、环境准备、不同运行模式测试

    目录: 入门(上) HDFS(中) MapReduce&Yarn(下) 优化(补充) 一.大数据概述 概念 特点:VVVV 应用场景 二.Hadoop到大数据生态 1.Hadoop生态圈.发展 ...

  9. 【企业流行新数仓】Day01:新版本对比、业务和表的介绍☆、Hive、ODS层、DWD层

    一.2.0版本对比 二.业务介绍 1.术语 SKU SPU UV: user views 用户浏览总量[浏览量] PV:page views 页面浏览总量 2.电商业务表结构 表名 同步方式 字段名 ...

  10. codeforce E - Binary Inversions题解

    题目: 给你一个01串,现在你可以(或者不用)选取其中一个元素进行一次反转操作0-1,1-0:从而使得串中的逆序对个数最多. 题目链接:codeforce origin problem 思路: 1. ...