SQL Server 事务隔离级别
一、事务隔离级别控制着事务的如下表现:
- 读取数据时是否占用锁以及所请求的锁类型。
- 占用读取锁的时间。
- 引用其他事务修改的行的读操作是否:
- 在该行上的排他锁被释放之前阻塞其他事务。
- 检索在启动语句或事务时存在的行的已提交版本。
- 读取未提交的数据修改。
以上说明事务隔离级别主要针对读操作来说的。(DML语句我们可以不考虑事务隔离级别,因为任何事物隔离级别下DML的加锁都很严格,属于得不到就等待的类型)
二、脏读、不可重复读、幻读的区别:
提到事物隔离级别就不能不提这3个概念,可以说事务隔离级别就是为了避免这3种情况出现的。
脏读:读到了其他事务已修改但未提交的数据
不可重复读:由于其他事务的修改,导致同一事务中两次查询读到的数据不同
幻读:由于其他事务的修改,导致同一事务中两次查询读到的记录数不同
可能有人对幻读和不可重复读的定义不太理解,两者最大的区别实质上在于加锁的不同,后边会有讲解。
三、ANSI/ISO标准定义了下列事务隔离级别,SQL Server数据库引擎支持全部这4种隔离级别:

因此四种隔离级别与脏读、幻读、不可重复读的对应情况如下:

需要特别提醒的是:虽然Mysql、Oracle所支持的事务隔离级别也基本遵循ANSI标准,但却有很大区别:
- Oracle只支持已提交读和序列化读。
Mysql默认的的可重复读隔离级别通过范围锁实现了避免幻读。
四、除以上4种隔离级别外SQL Server还支持使用行版本控制的其他两个事务隔离级别:
一个是默认的read committed隔离级别下的snapshot实现,严格来说并不算一个事务隔离级别,只是read committed的一个特殊形态。
一个是全新的事务隔离级别----快照隔离级别。
两者的开启方式为:
1、如果要开启SNAPSHOT事务隔离级别,需要预先设置ALLOW_SNAPSHOT_ISOLATION为ON,且目前只能修改会话级别的事务隔离级别。
ALTER DATABASE [dbname] SET ALLOW_SNAPSHOT_ISOLATION ON; --需要单用户模式下修改,因为要加库级别的独占锁。
然后执行如下语句修改事务隔离级别:(修改后只在会话级别生效,无法修改全局级别的事务隔离级别)
SET TRANSACTION ISOLATION LEVEL
{ READ UNCOMMITTED
| READ COMMITTED
| REPEATABLE READ
| SNAPSHOT
| SERIALIZABLE
}
2、使用READ_COMMITTED_SNAPSHOT,则直接执行下列ALTER语句修改,是在默认的READ COMMITTED隔离级别下修改的,此隔离级别修改后永久生效,使用dbcc useroptions查看可以看到事务隔离级别被全局的修改成了read committed snapshot。
ALTER DATABASE [dbname] SET READ_COMMITTED_SNAPSHOT ON;
两者的区别在于:
READ_COMMITTED_SNAPSHOT是指Select语句总是读取最新的已提交的数据,即如果有DML事务正在执行,那么select语句不会被阻塞而是读取这些DML事务预先生成的前镜像,这种读只会在表上加Sch-S锁,其他的行锁页锁全部没有。DML数据一旦提交,再次执行Select语句就会立马读到新的数据。
SNAPSHOT隔离级别与上述的区别在于,如果你在同一个事务内执行两次相同的select语句,那么即便在这两次select语句之间发生了数据更改且提交,两次读到的数据也是一样的。
用官网的一句话来描述两者区别就是:READ_COMMITTED_SNAPSHOT提供语句级的一致性,SNAPSHOT事务隔离级别提供事务级的一致性。
五、全部6种隔离级别的加锁模式:
开始说过事务隔离级别主要就是控制读操作加什么锁,锁占用多长时间的的,因此只有搞清各事务隔离级别下的加锁机制才能彻底搞清事务隔离级别的概念和他们的不同。
1.未提交读
2.已提交读
select语句对读取的数据正常加锁,但是不等事务结束才释放锁,而是读完一个页就会释放,会出现不可重复读和幻读。DML语句正常加锁。
3.已提交读快照
SQL Server特有的隔离级别,主要是为了匹配Oracle的已提交读实现的功能,在此隔离级别下,select只会对表加一个Sch-S锁,因此select不会引发在阻塞,但是会加大tempdb的使用量。DML正常加锁。
4.快照
同上,select也只加Sch-S锁,唯一区别在于实现的一致性读是事务级别的,即快照在tempdb中保留的时间更长。DML正常加锁。
这里猜测快照读隔离级别下会在事务第一次select时在tempdb中建立一个完整的快照,而不是仅依赖于MVCC的行版本机制。
5.可重复读
可重复读加的锁与已提交读完全一致,区别在于只有在整个事务完成后才会释放锁,而不是读完一个页就释放,此种加锁方式也避免了不可重复读,因为事务期间其他DML无法获取资源上的锁。
此隔离级别下可以避免不可重复读,但是不可避免幻读。DML正常加锁。
6.序列化读
序列化读加的锁与已提交读有区别,此隔离级别下select操作对索引键加的是键范围锁,而不是普通的S、U、X、IS、IU、IX等。
键范围锁的机制基本与Mysql中的范围锁相似,主要是为了防止幻读,其机制在于select操作不但会将读到的键值锁定,还会将上下键值的范围也锁定。
举例如下:
有主键为1,5,8,9,10的记录,select ... where col between 3 and 7;会使用键范围锁将5这条记录锁定,除此之外还会用一个键范围锁将346这几个虚幻的记录也锁定,这样就不能在读取操作期间插入数据了,可以防止幻读。
Ps:对于序列化加的键范围锁是否是我上边所说的那么精确,还需要具体实验,这里只是根据官网猜测会使用多余的一个键范围锁锁定可能造成幻读的记录(总的键范围锁数目为n+1个,n为满足查询条件的行数),具体实验方法参见我的另一篇博客,有兴趣的可以试试。
http://www.cnblogs.com/leohahah/p/7059852.html
总结:
可以看到SQL Server通过MVCC多版本控制机制在3、4两种隔离级别下实现select语句的不加锁读取,避免了阻塞。在已提交读快照隔离级别下通过mvcc实现了select不阻塞,但是依然会有不可重复读和幻读现象。在快照隔离级别下通过mvcc实现了select不阻塞,同时由于是事务级的快照,也顺带避免了不可重复读和幻读。因此可以发现幻读的解决方式目前只有两种:1是键范围锁,2是mvcc机制的事务级镜像(即snapshot隔离级别的方式)。
Ps:关于Mvcc机制的实现方式参考https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/sql/snapshot-isolation-in-sql-server,但是此文中关于snapshot和read_committed_snapshot的解释有些矛盾,文中把这两种隔离级别混淆了,但是事实上通过试验可以看到这两种isolation level的差别与Mysql中RR和RC下一致性读的差别是很相似的。正如我之前所写的snapshot实现的是事务级的一致性,而read_committed_snapshot实现的是语句级的一致性。
参考文档:
https://docs.microsoft.com/zh-cn/sql/t-sql/statements/set-transaction-isolation-level-transact-sql
https://msdn.microsoft.com/zh-cn/library/jj856598(v=sql.120).aspx
SQL Server 事务隔离级别的更多相关文章
- SQL Server 事务隔离级别详解
标签: SQL SEERVER/MSSQL SERVER/SQL/事务隔离级别选项/设置数据库事务级别 SQL 事务隔离级别 概述 隔离级别用于决定如果控制并发用户如何读写数据的操作,同时对性能也有一 ...
- 【转】SQL Server 事务隔离级别详解
SQL 事务隔离级别 概述 隔离级别用于决定如果控制并发用户如何读写数据的操作,同时对性能也有一定的影响作用. 步骤 事务隔离级别通过影响读操作来间接地影响写操作:可以在回话级别上设置事务隔离级别也可 ...
- SQL Server事务隔离级别
事务 定义 事务是作为单个逻辑工作单元执行的一系列操作. 一个逻辑工作单元必须有四个属性,称为原子性.一致性.隔离性和持久性 (ACID) 属性,只有这样才能成为一个事务. 一个事务可以包含多个操作. ...
- 理解Sql Server 事务隔离层级(Transaction Isolation Level)
关于Sql Server 事务隔离级别,百度百科是这样描述的 隔离级别:一个事务必须与由其他事务进行的资源或数据更改相隔离的程度.隔离级别从允许的并发副作用(例如,脏读或虚拟读取)的角度进行描述. 隔 ...
- Transcation And Lock--SQL SERVER 事务隔离级别
SQL SERVER 事务隔离级别:1.未提交读(READ UNCOMMITED) 允许脏读,读取数据时不加共享锁,与使用WITH(NOLOCK)结果相同2.已提交读 不允许脏读,读取数据 ...
- sql server 事务隔离性 snapshot 、read committed说明
一. --该 read committed 默认事务隔离级别 在 systemuser修改事务未完成时 select * from [SystemUser] where id=62; 该语句是不可读取 ...
- sql设置事务隔离级别
SET TRANSACTION一共有以下几种级别: SET TRANSACTION ISOLATION LEVEL { READ UNCOMMITTED | READ COMMITTED | REPE ...
- oracle,mysql,sql server三大数据库的事务隔离级别查看方法
1:mysql的事务隔离级别查看方法 mysql 最简单,执行这条语句就行:select @@tx_isolation 详情: 1.查看当前会话隔离级别 select @@tx_isolation; ...
- Sql Server 事务隔离级别的查看及更改
根据自身 Sql Server 的情况来自定义 事务隔离级别,将会更加的满足需求,或提升性能.例如,对于逻辑简单的 Sql Server,完全可以使用 read uncommitted 模式,来减少死 ...
随机推荐
- go使用context包避免goroutine泄露问题
go是带内存自动回收的特性,因此内存一般不会泄漏.但是Goroutine确存在泄漏的情况,同时泄漏的Goroutine引用的内存同样无法被回收. 下面的程序中后台Goroutine向管道输入自然数序列 ...
- 【SqlServer系列】数据库三大范式
1 概述 一般地,在进行数据库设计时,应遵循三大原则,也就是我们通常说的三大范式,即第一范式要求确保表中每列的原子性,也就是不可拆分:第二范式要求确保表中每列与主键相关,而不能只与主键的某部分相关 ...
- pytorch模型部署在MacOS或者IOS
pytorch训练出.pth模型如何在MacOS上或者IOS部署,这是个问题. 然而我们有了onnx,同样我们也有了coreML. ONNX: onnx是一种针对机器学习设计的开放式文件格式,用来存储 ...
- centos7部署DNS-1
文章索引: 一.服务相关介绍 二.实验:搭建正向主DNS服务器 三.实验:搭建反向解析服务器 四.实验:泛域名解析,如wwww.baidu.com也可以正常访问 环境 服务器 节点名称 IP地址 dn ...
- [转]chrome浏览器中 F12 功能的简单介绍
本文转自:https://www.cnblogs.com/zhuzhubaoya/p/9758648.html chrome浏览器中 F12 功能的简单介绍 由于F12是前端开发人员的利器,所以我自己 ...
- WPF系列(1)WPF和XAML基础
终于下定决心开始更新WPF一个系列的文章,这里主要是出于两个目的,一是自己对所学的知识有一个系统的总结,二十希望能对其他人有些帮助,如果您觉得我写的不好,欢迎提意见. 那么既然我要开始写WPF,那我们 ...
- C#调用存储过程执行缓慢,但在数据库中执行却很快的问题
参考: http://www.debugease.com/mssqlbasic/976568.html https://www.cnblogs.com/Irving/p/3951220.html ht ...
- [PHP]算法-跳台阶问题的PHP实现
一只青蛙一次可以跳上1级台阶,也可以跳上2级.求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果). 思路: 1.找规律 f(1)=1 f(2)=2 f(3)=3 f(4)=5 f( ...
- SpringMVC表单验证与Velocity整合
阅读本文约“1.2分钟” 定义表单类 以Login为例,有username和password两个字段 import javax.validation.constraints.NotNull; impo ...
- python面向对象学习(二)基本语法
目录 1. dir内置函数 2. 定义简单的类(只包含方法) 2.1 定义只包含方法的类 2.2 创建对象 2.3 编写第一个面向对象程序 3. 方法中的self参数 3.1 案例改造 -- 给对象添 ...