SQL Server with(nolock)详解

原文:SQL Server with(nolock)详解

大家在写查询时,为了性能,往往会在表后面加一个nolock,或者是with(nolock),其目的就是查询是不锁定表,从而达到提高查询速度的目的。

什么是并发访问:同一时间有多个用户访问同一资源,并发用户中如果有用户对资源做了修改,此时就会对其它用户产生某些不利的影响,例如:

1:脏读,一个用户对一个资源做了修改,此时另外一个用户正好读取了这条被修改的记录,然后,第一个用户放弃修改,数据回到修改之前,这两个不同的结果就是脏读。

2:不可重复读,一个用户的一个操作是一个事务,这个事务分两次读取同一条记录,如果第一次读取后,有另外用户修改了这个数据,然后第二次读取的数据正好是其它用户修改的数据,这样造成两次读取的记录不同,如果事务中锁定这条记录就可以避免。

3:幻读,指用户读取一批记录的情况,用户两次查询同一条件的一批记录,第一次查询后,有其它用户对这批数据做了修改,方法可能是修改,删除,新增,第二次查询时,会发现第一次查询的记录条目有的不在第二次查询结果中,或者是第二次查询的条目不在第一次查询的内容中。

为什么会在查询的表后面加nolock标识?为了避免并发访问产生的不利影响,SQL Server有两种并发访问的控制机制:锁、行版本控制,表后面加nolock是解决并发访问的方案之一。

1> 锁,每个事务对所依赖的资源会请求不同类型的锁,它可以阻止其他事务以某种可能会导致事务请求锁出错的方式修改资源。当事务不再依赖锁定的资源时,锁将被释放。

锁的类型:1:表类型:锁定整个表;2:行类型:锁定某个行;3:文件类型:锁定某个数据库文件;4:数据库类型:锁定整个数据库;5:页类型:锁定8K为单位的数据库页。

锁的分类还有一种分法,就是按用户和数据库对象来分:

1). 从数据库系统的角度来看:分为独占锁(即排它锁),共享锁和更新锁

1:共享 (S) :用于不更改或不更新数据的操作(只读操作),一般常见的例如select语句。

2:更新 (U) :用于可更新的资源中。防止当多个会话在读取、锁定以及随后可能进行的资源更新时发生常见形式的死锁。

3:排它 (X) :用于数据修改操作,例如 INSERT、UPDATE 或 DELETE。确保不会同时同一资源进行多重更新。

2). 从程序员的角度看:分为乐观锁和悲观锁。

1:乐观锁:完全依靠数据库来管理锁的工作。

2:悲观锁:程序员自己管理数据或对象上的锁处理。

一般程序员一看到什么锁之类,觉的特别复杂,对专业的DBA当然是入门级知识了。可喜的是程序员不用去设置,控制这些锁,SQLServer通过设 置事务的隔离级别自动管理锁的设置和控制。锁管理器通过查询分析器分析待执行的sql语句,来判断语句将会访问哪些资源,进行什么操作,然后结合设定的隔 离级别自动分配管理需要用到的锁。

2>:行版本控制:当启用了基于行版本控制的隔离级别时,数据库引擎 将维护修改的每一行的版本。应用程序可以指定事务使用行版本查看事务或查询开始时存在的数据,而不是使用锁保护所有读取。通过使用行版本控制,读取操作阻 止其他事务的可能性将大大降低。也就是相当于针对所有的表在查询时都会加上nolock,同样会产生脏读的现象,但差别在于在一个统一管理的地方。说到了基于行版本控制的隔离级别,这里有必要说下隔离级别的概念。

隔离级别的用处:控制锁的应用,即什么场景应用什么样的锁机制。

最终目的:解决并发处理带来的种种问题。

隔离级别的分类:

1:未提交读,隔离事务的最低级别,只能保证不读取物理上损坏的数据;

2:已提交读,数据库引擎的默认级;

3:可重复读;

4:可序列化;隔离事务的最高级别,事务之间完全隔离。

小结:NOLOCK 语句执行时不发出共享锁,允许脏读 ,等于 READ UNCOMMITTED事务隔离级别 。nolock确实在查询时能提高速度,但它并不是没有缺点的,起码它会引起脏读。

nolock的使用场景(个人观点):

1:数据量特别大的表,牺牲数据安全性来提升性能是可以考虑的;

2:允许出现脏读现象的业务逻辑,反之一些数据完整性要求比较严格的场景就不合适了,像金融方面等。

3:数据不经常修改的表,这样会省于锁定表的时间来大大加快查询速度。

综上所述,如果在项目中的每个查询的表后面都加nolock,这种做法并不科学,起码特别费时间,不如行版本控制来的直接有效。

而且会存在不可预期的技术问题。应该有选择性的挑选最适合的表来放弃共享锁的使用。

最后说下nolockwith(nolock)的几个小区别:

1:SQL05中的同义词,只支持with(nolock);

2:with(nolock)的写法非常容易再指定索引。

跨服务器查询语句时 不能用with (nolock) 只能用nolock
同一个服务器查询时 则with (nolock)和nolock都可以用 
比如

SQL code

select * from [IP].a.dbo.table1 with (nolock) 这样会提示用错误

select * from a.dbo.table1 with (nolock) 这样就可以

时间: 2024-10-27 05:34:15

SQL Server with(nolock)详解的相关文章

SQL Server表分区详解

原文:SQL Server表分区详解 什么是表分区 一般情况下,我们建立数据库表时,表数据都存放在一个文件里. 但是如果是分区表的话,表数据就会按照你指定的规则分放到不同的文件里,把一个大的数据文件拆分为多个小文件,还可以把这些小文件放在不同的磁盘下由多个cpu进行处理.这样文件的大小随着拆分而减小,还得到硬件系统的加强,自然对我们操作数据是大大有利的. 所以大数据量的数据表,对分区的需要还是必要的,因为它可以提高select效率,还可以对历史数据经行区分存档等.但是数据量少的数据就不要凑这个热

JDBC连接SQL Server 2005步骤详解

一.设置SQL Server服务器:    1."开始" → "程序" → "Microsoft SQL Server 2005" → "配置工具" → "SQL Server Configuration Manager"(确认"SQL Server Management Studio"已关闭)    2."SQL Server 2005 服务"中停止服务"

SQL Server:触发器详解

SQL Server:触发器详解 1. 概述 2. 触发器的分类 3. Inserted和Deleted表 4. 触发器的执行过程 5. 创建触发器 6. 修改触发器: 7. 删除触发器: 8. 查看数据库中已有触发器: 9. “Instead of”相关示例: 10. “After”触发器 11. 参考资源 1. 概述 触发器是一种特殊的存储过程,它不能被显式地调用,而是在往表中插入记录﹑更新记录或者删除记录时被自动地激活. 所以触发器可以用来实现对表实施复杂的完整性约束. 2. 触发器的分类

SQL Server 字符串 参数详解

1:Integrated Security参数     当设置Integrated Security为 True 的时候,连接语句前面的 UserID, PWD 是不起作用的,即采用windows身份验证模式.     只有设置为 False 或省略该项的时候,才按照 UserID, PWD 来连接.     Integrated Security 还可以设置为:sspi ,相当于 True,建议用这个代替 True. 2:参数Trusted_Connection     Trusted_Con

Java调用SQL Server的存储过程详解

转载自Microsoft的官方文档 http://msdn2.microsoft.com/zh-cn/library/ms378995.aspx收录于 www.enjoyjava.net/f25 本文较长,包含了如下几部分 使用不带参数的存储过程 使用带有输入参数的存储过程 使用带有输出参数的存储过程 使用带有返回状态的存储过程 使用带有更新计数的存储过程 1使用不带参数的存储过程 使用 JDBC 驱动程序调用不带参数的存储过程时,必须使用 call SQL 转义序列.不带参数的 call 转义

SQL Server计数器属性详解

常规计数器 收集操作系统服务器的服务器性能信息,包括Processor.磁盘.网络.内存 Processor 处理器 1.1 % Processor Time指处理器用来执行非闲置线程时间的百分比.通过此计数器可以确定服务器当前CPU使用百分比. 1.2 % Privileged Time是在特权模式下进程线程执行代码所花时间的百分比.当调用 Windows 系统服务时,此服务经常在特权模式运行,以便获取对系统专有数据的访问. PhysicalDisk物理磁盘(某个RAID) 2.1 Avg.

Cacti 监控 SQL Server 数据库图文详解

模板下载: (1)可以直接下载本站发布的 Cnyunwei-Cacti+Nagios 集成全自动安装ISO进行安装,已集成此模板及更多的使用插件模板(2)可以直接去官方论坛下载最新的模板 http://forums.cacti.net/viewtopic.php?f=12&t=38135 php-mssql配置: cacti的机器上必须有php-mssql驱动php -m | grep mssql 查看是否有mssql,如没有安装的话,直接yum安装即可 yum install php-mssq

(转)Java调用SQL Server的存储过程详解

本文转载自:http://dev.yesky.com/128/8088128.shtml 1使用不带参数的存储过程 使用 JDBC 驱动程序调用不带参数的存储过程时,必须使用 call SQL 转义序列.不带参数的 call 转义序列的语法如下所示: 以下是引用片段:{call procedure-name} 作为实例,在 SQL Server 2005 AdventureWorks 示例数据库中创建以下存储过程: 以下是引用片段:CREATE PROCEDURE GetContactForma

Sql Server之数据类型详解

  数据类型是一种属性,用于指定对象可保存的数据的类型,SQL Server中支持多种数据类型,包括字符类型.数值类型以及日期类型等.数据类型相当于一个容器,容器的大小决定了装的东西的多少,将数据分为不同的类型可以节省磁盘空间和资源.  Sql Server 还能自动限制每个数据类型的取值范围,例如定义了一个类型为int的字段,如果插入数据时插入的值的大小在smallint或者tinyint范围之内, Sql Server 会自动将类型转换为smallint 或者tinyint,这样一来,在存储