Transaction And Lock--READ COMMITTED隔离级别下的"脏读"
在READ UNCOMMITTED事务隔离级别下或使用WITH(NOLOCK)来查询数据时,会出现脏读情况,因此对于一些比较"关键"的业务,会要求不能使用WITH(NOLOCK)或允许在READ UNCOMMITTED事务隔离级别下,于是我们使用默认的READ COMMITTED隔离级别来访问数据,但是这样真的就没有问题么?
让我们来做个小实验
准备测试数据
--=======================================
--创建测试表
CREATE TABLE TB106
(
C0 INT IDENTITY(1,1) PRIMARY KEY,
C1 INT,
C2 CHAR(100),
C3 NVARCHAR(4000)
) GO
--=======================================
--创建一个非聚簇索引
CREATE INDEX IX_C1_C2
ON TB106(C1,C2)
GO
--=======================================
--向表中填充1000条数据
DECLARE @ID INT
SET @ID=0
WHILE(@ID<1000)
BEGIN
INSERT INTO TB106(C1,C2,C3)
SELECT @ID,@ID,
REPLICATE('A',3800) SET @ID=@ID+1 END
GO
--=================================
--查看表中数据,共1000行
SELECT * FROM TB106
开启回话1,运行以下脚本
--======================
--开启事务,更新C0为100的数据
BEGIN TRAN
UPDATE TB106
SET C1=101
WHERE C0=100
开启回话2,运行以下脚本
--=======================
--查询数据
SELECT C1,C2,C0 FROM TB106
我们会发现回话2被回话1阻塞,但是已经有少量数据开始被读取

我们再次回到回话1,继续执行以下脚本
--=====================
--更新C0为5的数据,并提交事务
UPDATE TB106
SET C1=1000
WHERE C0=5 COMMIT
伴随着回话1事务的提交,回话2没有了阻塞,顺利完成查询,但是奇迹出现了

表中只有1000行数据,为什么我们能查出1001行数据来呢?
我们来分析下执行结果,不难发现c0=5的数据被读取了两遍,更新前后的数据都被读取到,这不科学!在c0=5的数据被更新前,数据被读取了一遍,然后当读到c0=100的时候,回话被阻塞,然后c0=5的数据被更新,更新后的数据记录存放位置变动,移到了索引尾部,当阻塞结束后,该记录又再次被读取,从而导致一行记录被读取两遍。
--=====================================================================
这并不是MS的bug,让我们来仔细阅读下各种隔离级别的解释:
READ UNCOMMITTED 指定语句可以读取已由其他事务修改但尚未提交的行。 在 READ UNCOMMITTED 级别运行的事务,不会发出共享锁来防止其他事务修改当前事务读取的数据。READ UNCOMMITTED 事务也不会被排他锁阻塞,排他锁会禁止当前事务读取其他事务已修改但尚未提交的行。设置此选项之后,可以读取未提交的修改,这种读取称为脏读。在事务结束之前,可以更改数据中的值,行也可以出现在数据集中或从数据集中消失。该选项的作用与在事务内所有 SELECT 语句中的所有表上设置 NOLOCK 相同。这是隔离级别中限制最少的级别。
READ COMMITTED 指定语句不能读取已由其他事务修改但尚未提交的数据。这样可以避免脏读。其他事务可以在当前事务的各个语句之间更改数据,从而产生不可重复读取和幻像数据。该选项是 SQL Server 的默认设置。
REPEATABLE READ 指定语句不能读取已由其他事务修改但尚未提交的行,并且指定,其他任何事务都不能在当前事务完成之前修改由当前事务读取的数据。 对事务中的每个语句所读取的全部数据都设置了共享锁,并且该共享锁一直保持到事务完成为止。这样可以防止其他事务修改当前事务读取的任何行。其他事务可以插入与当前事务所发出语句的搜索条件相匹配的新行。如果当前事务随后重试执行该语句,它会检索新行,从而产生幻读。由于共享锁一直保持到事务结束,而不是在每个语句结束时释放,所以并发级别低于默认的 READ COMMITTED 隔离级别。此选项只在必要时使用。
--=====================================================================
误区:不知道有多少朋友和我一样,错误认为REPEATABLE READ分离级别只是为了保证两次SQL查询的数据不发生变化,而忽略了在一次查询期间内数据发生变化导致的问题。而由于导致该问题的发生概率比较低,往往不能引起我们足够重视,从而错误地认为READ COMMITTED隔离级别可以胜任类似需求。
--======================================================================
依旧是妹子压贴

Transaction And Lock--READ COMMITTED隔离级别下的"脏读"的更多相关文章
- Mysql 间隙锁原理,以及Repeatable Read隔离级别下可以防止幻读原理(百度)
Mysql知识实在太丰富了,前几天百度的面试官问我MySql在Repeatable Read下面是否会有幻读出现,我说按照事务的特性当然会有, 但是面试官却说 Mysql 在Repeatable Re ...
- [原创]MySQL RR隔离级别下begin或start transaction开启事务后的可重复读?
Server version: 5.6.21-log MySQL Community Server (GPL) 前提提要: 我们知道MySQL的RR(repeatable read)隔 ...
- mysql 开发进阶篇系列 12 锁问题(隔离级别下锁的差异)
1. innodb在不同隔离级别下的一致性读及锁的差异 不同的隔离级别下,innodb处理sql 时采用的一致性读策略和需要的锁是不同的,同时,数据恢复和复制机制的特点,也对一些sql的一致性读策略和 ...
- MySQL Transaction--RR事务隔离级别下加锁测试
============================================================================== 按照非索引列更新 在可重复读的事务隔离级别 ...
- MySQL Transaction--RC事务隔离级别下加锁测试
==============================================================================非索引列更新 在读提交的事务隔离级别下,在非 ...
- mysql中不同事务隔离级别下数据的显示效果--转载
事务是一组原子性的SQL查询语句,也可以被看做一个工作单元.如果数据库引擎能够成功地对数据库应用所有的查询语句,它就会执行所有查询,如果任何一条查询语句因为崩溃或其他原因而无法执行,那么所有的语句就都 ...
- 浅谈mysql中不同事务隔离级别下数据的显示效果
事务的概念 事 务是一组原子性的SQL查询语句,也可以被看做一个工作单元.如果数据库引擎能够成功地对数据库应用所有的查询语句,它就会执行所有查询,如果任何一条查 询语句因为崩溃或其他原因而无法执行,那 ...
- 浅析SQL Server在可序列化隔离级别下,防止幻读的范围锁的锁定问题
本文出处:http://www.cnblogs.com/wy123/p/7501261.html (保留出处并非什么原创作品权利,本人拙作还远远达不到,仅仅是为了链接到原文,因为后续对可能存在的一些错 ...
- Transaction And Lock--快照事务隔离级别
--================================================--准备数据GOCREATE DATABASE DB5GOUSE DB5GOCREATE TABLE ...
随机推荐
- could not load inserted library: /usr/lib/libgmalloc.dylib
本人也刚开始学习iphone开发,最近维护一个程序时,不知道怎么弄的,不能build到真机了,到模拟器没有什么问题,出现的错误是 :---->>>could not load ins ...
- .Net中集合排序
public class StockQuantity { public StockQuantity(string status, DateTime dateTime, int quantity) { ...
- Matlab Codes and Datasets for Feature Learning
Matlab Codes and Datasets for Feature Learning 浙江大学CAiDeng提供的Matlab特征学习Code.
- ibatis.net:第四天,Update 和 Delete
xml <update id="UpdateOrder" parameterClass="Order"> UPDATE [Orders] SET C ...
- @NotBlank注解使用不生效的解决办法
@NotBlank注解使用时必须在入参处(controller)加@Valid. 如: public Class User{ @NotBlank(message = "用户名不能为空&quo ...
- 我们的生活第二季/全集This Is Us迅雷下载
NBC剧集<我们这一天>宣布一次性续订2.3季,这部Dan Fogelman打造的大热剧是这个秋季档收视人数第二的广播网剧情剧.新续订的两季还是每季18集. NBC的叫好叫座剧<我们 ...
- 女子监狱第一季/全集Orange Is the New Black迅雷下载
本季第一季 Orange Is the New Black 1 (2013) 看点:该剧描述主人公Piper Chapman(Taylor Schilling)在大学里结识了毒贩Alex(Laura ...
- TextView字体,行距,html格式,超链接,最大长度的设定
颜色,大小 <!-- 设置字体的大小,推荐用sp做单位:字体颜色以#开头 --> <TextView android:id="@+id/textView1" an ...
- Kubernetes中Pod的健康检查
本文介绍 Pod 中容器健康检查相关的内容.配置方法以及实验测试,实验环境为 Kubernetes 1.11,搭建方法参考kubeadm安装kubernetes V1.11.1 集群 0. 什么是 C ...
- PHP导出大数据
保存到本地 <?php // a db link for queries $lh = mysql_connect( '127.0.0.1', 'root', '' ); // and a con ...