一些人总当NOLOCK查询提示是SQL Server里的加速器,因为它避免了大量的死锁情景。在这篇文章里,我想向你展示下为什么NOLOCK查询提示是个不好的想法。

脏读(Dirty Reads)

NOLOCK查询提示一个最大的副作用就是在你的记录集会出现所谓的脏读这个事实。我们来看下面的代码:

 BEGIN TRANSACTION

 UPDATE Person.Person
SET FirstName = 'James'
WHERE LastName = 'Jones'

如你所见,我开始了一个新的事务,对AdventureWorks2012数据库里的Person.Person表进行UPDATE语句。现在当你尝试同时在另一个会话里读取这个记录时,这个SELECT语句会阻塞——在这个情况下请求的共享锁(S)会被已经授予的排它锁(X)阻塞——写阻塞读操作。

 SELECT
FirstName,
LastName
FROM Person.Person
WHERE LastName = 'Jones'
GO

一些人现在回应用SQL Server里的加速器,使用NOLOCK查询提示:

 SELECT
FirstName,
LastName
FROM Person.Person WITH (NOLOCK) -- It's a kind of magic...
WHERE LastName = 'Jones'
GO

如你所见死锁情景马上解决了,你从SQL Server返回记录了——遗憾的是在你面前现在有脏读(Dirty Read):你读取了尚未提交的数据。假设现在用UPDATE语句的第1个事务回滚了:在这个情况下,你已读取的数据在SQL Server里逻辑上是从未存在的。

因此NOLOCK查询提示并不是在每个情景都是有用的。 如果你想运行一个报表,或者你只想快速返回结果,记录不用100%正确,这“可以是”个可取的(考虑下一天的平均销售额)。当然,当你需要精确的结果,NOLOCK并不可取。当然也有一些特定场景即使NOLOCK也会阻塞

读提交快照隔离(Read Committed Snapshot Isolation (RCSI))

有人给我提了为什么NOLOCK查询提示基本是一个不方便的(no-go)的选择:你不能在明显的方式里切换你的数据库查询到读提交快照隔离(Read Committed Snapshot Isolation (RCSI))。我从未想过这个情景,但没错是对的。读提交快照隔离(Read Committed Snapshot Isolation (RCSI))是个数据库选项。当你启用它的时候,每个查询都是在新的读提交快照乐观隔离级别里——只要在你的事务里不指定任何隔离级别。

对于特定的SQL语句使用NOLOCK查询提示,你临时修改隔离级别为未提交读(Read Uncommitted)。因此SQL语句也不会从读提交快照隔离受益,因为语句并没有在默认的提交读( Read Committed)隔离运行。这就对了!当你下次写下神奇的……WITH(NOLOCK)……时,好好想下这个额外参数。

小结

使用NOLOCK查询提示运行每个查询并不都有意义。一方面你会通过脏读(Dirty Reads)返回不一致的数据。另一方面你不能从读提交快照隔离(Read Committed Snapshot Isolation (RCSI))乐观隔离级别里受益,因为你临时修改了你SQL语句的默认隔离级别。

感谢关注!

参考文章:

https://www.sqlpassion.at/archive/2015/06/15/why-the-query-hint-nolock-is-a-bad-idea/

为什么NOLOCK查询提示是个不明智的想法的更多相关文章

  1. EntityFramework Core 3.x添加查询提示(NOLOCK)

    前言 前几天看到有园友写了一篇关于添加NOLOCK查询提示的博文<https://www.cnblogs.com/weihanli/p/12623934.html>,这里呢,我将介绍另外一 ...

  2. sql 优化 链接提示 查询提示 标提示

    SQL Server的查询优化器在select查询执行的时候产生一个高效的查询执行计划.如果优化器不能选择最优的计划,那么就需要检查查询计划.统计信息.支持的索引等,而通过使用提示可以改变优化器选择查 ...

  3. Sql Server优化之索引提示----我们为什么需要查询提示,Sql Server默认情况下优化策略选择的不足

    环境: Sql Server2012 SP3企业版,Windows Server2008 标准版 问题由来: 最近在做DB优化的时候,发现一个存储过程有非常严重的性能问题, 由于整个SP整体逻辑是一个 ...

  4. SQL Server调优系列玩转篇(如何利用查询提示(Hint)引导语句运行)

    前言 前面几篇我们分析了关于SQL Server关于性能调优的一系列内容,我把它分为两个模块. 第一个模块注重基础内容的掌握,共分7篇文章完成,内容涵盖一系列基础运算算法,详细分析了如何查看执行计划. ...

  5. 利用查询提示优化SQL

    数据库环境:SQL SERVER 2005 我们来看一下SQL语句及对应的数据量 SELECT COUNT(*) FROM cinvout_02 a WHERE ( a.dept_id IN ( SE ...

  6. MySQL查询提示

    MySQL查询提示: 1.LOW_PROPRITY,HIGHT_PRIORITY 作用:指定sql语句的运行优先级,会将加了HIGHT_PROPRITY提示的sql调度到表访问队列的最前面 限制:仅对 ...

  7. MySQL自成一派的查询提示

    [查询提示] MySQL中可以给select语句各种提示,比如告诉它“查询的结果集特别大,请直接用磁盘临时表”,“请让这条select优先执行” .... [查询提示:与结果集相关] 与结果集相关的查 ...

  8. SQL Server 调优系列玩转篇一(如何利用查询提示(Hint)引导语句运行)

    前言 前面几篇我们分析了关于SQL Server关于性能调优的一系列内容,我把它分为两个模块. 第一个模块注重基础内容的掌握,共分7篇文章完成,内容涵盖一系列基础运算算法,详细分析了如何查看执行计划. ...

  9. ECSHOP后台SQL查询提示错误 this sql May contain UPDATE,DELETE,TRUNCATE,ALTER,DROP,FLUSH,INSERT

    一).首先说一下错误现象:市面上流行的绝大部分ECSHOP模板,安装的时候都需要执行一段或几段SQL语句来修改数据结构或者初始化一些数据.大多数ECSHOP管理员为了省事,都会通过 “ECSHOP后台 ...

随机推荐

  1. 使用Gulp和Browserify创建多个绑定文件

    Browserify是一个Javascript的绑定工具,帮助我们理顺module之间的依赖关系.Gulp用来优化workflow.两者的共同点都是使用流,但在使用流方面也有不同之处: Browser ...

  2. 学习Swift,一定不能错过的10大开源项目!

    如果你是位iOS开发者,或者你正想进入该行业,那么Swift为你提供了一个绝佳的机会.Swift的设计非常优雅,较Obj-C更易于学习,当然也非常强大. 为了指导开发者使用Swift进行开发,苹果发布 ...

  3. 【Android开发坑系列】之Fragment

    这个东西有顾名思义是碎片,和之前的Activity对应. 坑1:一般情况都会想当然的以为进程被杀掉之后,Fragment也会被回收 其实,Fragment有自己的生命周期,有自己的管理器(Fragme ...

  4. ubuntu11.10搭建eclipse C++开发环境[zhuan]

    1.最重要的东西,C++必要工具,安装的是GCC工具链,Make等一系列开发工具: sudo apt-get install build-essential 2. 安装Eclipse sudo apt ...

  5. SVO实时全局光照:Sparse Voxel Octree based Global Illumination (SVO GI)

    功能已实现,初步集成进来,暂未进行重度优化.但GI的效果已很明显.这里特地给出了开启实时GI前后的效果对比,比对场景如下:1.只有直接光照(方向光源)的场景.2在直接光照(方向光源)基础上开启了实时G ...

  6. P2P资料

    常用链接 openstack创建实例的方法 http://www.cnblogs.com/popsuper1982/p/3800426.html qemu官网 http://wiki.qemu.org ...

  7. Codeforces Round #379 (Div. 2) B. Anton and Digits 水题

    B. Anton and Digits 题目连接: http://codeforces.com/contest/734/problem/B Description Recently Anton fou ...

  8. c# 小数取整

    向上取整 math.ceiling() = math.ceiling( math.ceiling( 向下取整 math.) = math. math. C#取整函数实例应用详解 C#取整函数的相关使用 ...

  9. Linux 输出文件列数,拼接文件

    如果我只想看看文件的前几行,每行的字段数(列数),我的文件已tab作为分隔符(这个可以自己指定),其具体命令如下: head fileName | awk -F'\t' '{print NF}' 如果 ...

  10. 实现 Dispose 方法

    实现 Dispose 方法 MSDN 类型的 Dispose 方法应释放它拥有的所有资源.它还应该通过调用其父类型的 Dispose 方法释放其基类型拥有的所有资源.该父类型的 Dispose 方法应 ...