Sql Server中的事务隔离级别
数据库中的事物有ACID(原子性,一致性,隔离性,持久性)四个特性。其中隔离性是用来处理并发执行的事务之间的数据访问控制。SqlServer中提供了几种不同级别的隔离类型。
概念
Read UnCommitted
当前事务可以读取其他事务已修改但还未提交的数据。如果其他事务进行数据Rollback,当前事务就会出现脏读,数据错误。
Read Committed
当前事务只能读取其他事务修改并且已提交的数据。这样避免了脏读。但是如果其他事务在当前事务两次读之间对数据修改,会导致当前事务两次相同读取操作得到的结果不一样。
Repeatable Read
在Read Committed基础上,当前事务在对相同数据的多次读之间,其他事务不能对数据进行修改。因此也就不会出现Read Committed中的多次读取数据不一致的情况。但是该类型下还会有一个问题,在两次数据读取之间,其他事务还是可以插入新的数据的,这样可能导致当前事务两次读取的数据数量不一样。
Serializiable
这个算是终极隔离级别了,在Repeatable Read的基础上,当前事务的两次数据读取之间,其他事务不能插入会出现在当前事务数据读取操作Where条件所表示范围内的数据。这样当前数据的两次相同的数据操作就不会返回不同数目的数据了。
新版的SQLServer中还有Snapshot隔离级别,以后有机会再研究。
实现原理
Sql Server中,事务隔离是通过锁的机制来实现的。算是我们所说的悲观并发的处理方式。
Read UnCommitted
这种类型下,Sql Server不会对数据加任何锁(写操作除外)。因此数据的读写就没有任何限制了。
Read Committed
这是Sql Server的默认事务隔离级别。其他事务进行写操作时,会对数据加排他锁知道事务结束;当前事务对数据进行读操作时,会对数据加共享锁(共享锁与排他锁冲突),因此如果有事务修改了数据没有提交,当前事务则无法获取到共享锁,而无法读取数据。这样解决脏读的问题。因为该级别下获取的共享锁在数据读取到后即失效,因此会出现重复读带来的问题。
Repeatable Read
在Read Committed级别的基础上,该级别下,读数据时的共享锁的有效期延长到了事务结束,因此这期间其他事务无法拿到排他锁对数据进行修改。因此解决了重复读的问题。
Serializiable
在Repeatable Read基础上,该级别读数据的时候会针对所读数据的范围(而不是只对读取到的数据)加共享锁。因此其他事务无法在该范围下插入数据。
存在问题
1. Repeatable Read和Serializiable解决了数据一致性的问题,但是牺牲了数据的并发访问能力。
2. Repeatable Read和Serializiable延长了共享锁到事务结束,这样会导致多个事务都拿到共享锁,但当它们都想获取数据的排他锁进行修改时,会形成死锁。因为互相都在等待对方释放共享锁。这种情况下的解决方案是如果在事务中需要对数据进行修改,改为获取更新锁(同一时间只有一个事务能拿到相同数据的更新锁)。这样就不会出现死锁的情况了。
SQL
在Sql Server中,可以通过SET TRANSACTION ISOLATION LEVEL命令来更改事务隔离类型。设置后统一数据库连接下会一直使用该隔离类型。但是如果在存储过程中设置隔离类型,存储过程在返回的时候,隔离类型恢复为调用存储过程之前的状态。因此在存储过程中设置的隔离类型只对该存储过程执行过程有效。
验证
Read UnCommitted
有如下数据:
ID Name Age
1 Je 3
在事务1中执行如下SQL
BEGIN TRAN
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
UPDATE Account SET AGE = 4 WHERE ID = 1
//此处没有提交事务
在事务2中再执行如下SQL
BEGIN TRAN
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
SELECT * FROM Account WHERE ID = 1
COMMIT
会得到如下结果
ID Name Age
1 Je 4
因此该隔离级别下,能读到未提交的修改。
Read Committed
将上面的代码中的隔离级别改为READ COMMITTED。得到的结果为事务2在读取数据时为一直处于等待状态。
执行如下代码查看锁的状态。
SELECT * FROM sys.dm_tran_locks where resource_type != 'DATABASE'
会发现事务2一直在等待获取共享锁。此时在事务1中执行COMMIT命令,事务2则可以继续执行,并且能拿到事务1提交的数据。
ID Name Age
1 Je 4
接下来按顺序执行如果代码
首先重置ID为1的数据的Age为3.
事务1
BEGIN TRAN
SET TRANSACTION ISOLATION LEVEL READ COMMITTED
SELECT * FROM Account WHERE ID = 1
WAITFOR DELAY '00:00:10'
SELECT * FROM Account WHERE ID = 1
COMMIT
事务2
BEGIN TRAN
SET TRANSACTION ISOLATION LEVEL READ COMMITTED
UPDATE Account SET AGE = 4 WHERE ID = 1
COMMIT
GO
事务1会得到如下结果:
ID Name Age
1 Je 3
ID Name Age
1 Je 4
两次读的结果不一样
Repeatable Read
上面的代码如果设置为Repeatable Read隔离类型,得到如下结果(先将行数据重置为age=3):
ID Name Age
1 Je 3
ID Name Age
1 Je 3
两次读操作的age值都为3,因为在事务1完成之前,事务2的写操作被block
如果执行如下代码:
事务1
BEGIN TRAN
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
SELECT * FROM Account WHERE ID >= 1;
WAITFOR DELAY '00:00:10';
SELECT * FROM Account WHERE ID >= 1;
COMMIT
事务2
BEGIN TRAN
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ
INSERT INTO Account values('Je2',3)
COMMIT
GO
事务1最终会得到如下结果
ID Name Age
1 Je 3
ID Name Age
1 Je 3
2 Je2 3
两次读结果的数量不一样。
Serializiable
如果将事务隔离级别设为Serializiable得到结果是
ID Name Age
1 Je 3
ID Name Age
1 Je 3
如果在事务1执行期间查看锁的情况。会发现事务1获得的锁的类型为RangeS-S。即范围锁。
Sql Server中的事务隔离级别的更多相关文章
- SQL Server 中的事务与事务隔离级别以及如何理解脏读, 未提交读,不可重复读和幻读产生的过程和原因
原本打算写有关 SSIS Package 中的事务控制过程的,但是发现很多基本的概念还是需要有 SQL Server 事务和事务的隔离级别做基础铺垫.所以花了点时间,把 SQL Server 数据库中 ...
- SQL Server中的事务与其隔离级别之脏读, 未提交读,不可重复读和幻读
原本打算写有关 SSIS Package 中的事务控制过程的,但是发现很多基本的概念还是需要有 SQL Server 事务和事务的隔离级别做基础铺垫.所以花了点时间,把 SQL Server 数据库中 ...
- SQL Server中的事务日志管理的阶梯,级别1:事务日志概述
SQL Server中的事务日志管理的阶梯,级别1:事务日志概述 翻译:刘琼滨 谢雪妮 许雅莉 赖慧芳 级别1:事务日志概述 事务日志是一个文件,其中SQL服务器存储了所有与日志文件关联的数据库执行的 ...
- 第16周翻译:SQL Server中的事务日志管理,级别3:事务日志、备份和恢复
源自: http://www.sqlservercentral.com/articles/Stairway+Series/73779/ 作者: Tony Davis, 2011/09/07 翻译:刘琼 ...
- Microsoft SQL Server中的事务与并发详解
本篇索引: 1.事务 2.锁定和阻塞 3.隔离级别 4.死锁 一.事务 1.1 事务的概念 事务是作为单个工作单元而执行的一系列操作,比如查询和修改数据等. 事务是数据库并发控制的基本单位,一条或者一 ...
- 【转】SQL Server中的事务与锁
SQL Server中的事务与锁 了解事务和锁 事务:保持逻辑数据一致性与可恢复性,必不可少的利器. 锁:多用户访问同一数据库资源时,对访问的先后次序权限管理的一种机制,没有他事务或许将会一塌糊涂 ...
- Innodb中的事务隔离级别和锁的关系
前言: 我们都知道事务的几种性质,数据库为了维护这些性质,尤其是一致性和隔离性,一般使用加锁这种方式.同时数据库又是个高并发的应用,同一时间会有大量的并发访问,如果加锁过度,会极大的降低并发处理能力. ...
- Innodb中的事务隔离级别和锁的关系(转)
原文:http://tech.meituan.com/innodb-lock.html 前言: 我们都知道事务的几种性质,数据库为了维护这些性质,尤其是一致性和隔离性,一般使用加锁这种方式.同时数据库 ...
- mysql中不同事务隔离级别下数据的显示效果--转载
事务是一组原子性的SQL查询语句,也可以被看做一个工作单元.如果数据库引擎能够成功地对数据库应用所有的查询语句,它就会执行所有查询,如果任何一条查询语句因为崩溃或其他原因而无法执行,那么所有的语句就都 ...
随机推荐
- MySQL "tinyInt1isBit or tinyint(1)" 相关问题解析
问题描述 tinyInt 的数据类型,在JAVA数据类型 和 MySQL的数据类型转换,要注意存储长度为 1 的情况.查询时,该字段对应的Java类型为Boolean 源数据: 读取后数据: 问题分析 ...
- Codeforces Round #307 (Div. 2) C. GukiZ hates Boxes 二分
C. GukiZ hates Boxes time limit per test 2 seconds memory limit per test 256 megabytes input standar ...
- linux下升级npm以及node
npm升级 废话不多说,直接讲步骤.先从容易的开始,升级npm. npm这款包管理工具虽然一直被人们诟病,很多人都推荐使用yarn,但其使用人数还是不见减少,况且npm都是随node同时安装好的,一时 ...
- a标记无效问题
当在<a href=''></a>这个标记中嵌入<td></td> 就会导致部分浏览器无法单击,所以在开发HTML页面的时候,一定不要在 a标记中嵌入 ...
- xssProject在java web项目中应用
注:转载http://337027773.blog.163.com/blog/static/54376980201451133534157/ 1.项目引入xssProtect-0.1.jar.antl ...
- do-while语句和while的区别
do-while语句是一种后测试循环语句,即只有在循环体中的代码执行之后,才会测试出口条件.其实就是,代码在刚开始执行的时候,都是要先走一遍do循环体内的代码,然后在与while里面的条件进行判断,成 ...
- ossim中Spot5模型bug修复
ossim中Spot5模型在读取像素视线角时存在一个严重的bug,导致某些点的视线角提取错误. 下面是ossim中getPixelLookAngleX 函数的代码: ossimSpotDimapSup ...
- WebApi用Post的方式提交Json时,获取不到值或不进对应方法的问题
又是一个通宵,终于搞明白了. 被WebApi坑得好惨. 之前用各种方法Post上来,有时可以读到结构,但没值,有时直接就是一个Null,有时连方法都没进就跑了,只是来控制器里看了一下…… 最后好友说还 ...
- 纪念又一次ak
t1网络流 随便建个图就可以了 t2单调队列 分成两组来做 t3dp+高精度 为了不被卡厂用了万进制
- 在JavaScript中进行文件处理,第三部分:处理事件和错误
译注:原文是<JavaScript高级程序设计>的作者Nicholas Zakas写的,本翻译纯属为自己学习而做,仅供参考.原文链接:这里 FileReader对象用来读取浏览器可以访问的 ...