SQL Server脏读方式数据提取--NOLOCK和READPAST

数据库 SQL Server
对数据库中的数据进行读操作或修改时,数据库引擎使用专门的控制类型来保持数据库的完整性,称为锁机制。锁机制通过确保包含在一个事务中的数据库记录在该事务提交之前不能被其它事务修改来保证数据库的一致性。

对数据库中的数据进行读操作或修改时,数据库引擎使用专门的控制类型来保持数据库的完整性,称为锁机制。锁机制通过确保包含在一个事务中的数据库记录在该事务提交之前不能被其它事务修改来保证数据库的一致性。

在设计数据库应用时,你应该记住各种不同类型的锁及事务发生的不同隔离级别。通常情况下,SQL Server默认方式能够很好地完成你要使用的功能,不过,有些时候利用SQL语句在数据表上手工添加关于锁是如何应用的提示信息将是十分有用的。

本文主要介绍了两种数据表提示:NOLOCK和READPAST。我们将建立一个数据表用作例子中的查询数据表。执行列表A中的脚本建立一个SalesHistory数据表并添加一些数据。

NOLOCK

该数据表提示,也称为READUNCOMMITTED,只能用于SELECT语句。NOLOCK表明没有对数据表添加共享锁以阻止其它事务对数据表数据的修改。

该语句的好处是它可以使数据库引擎不用在处理查询中的上锁问题,可以提高并发性并改善数据库性能,因为数据库引擎不用在维护共享锁的使用问题。存在的问题是因为该语句不能处理要读取的数据表的所有锁,所以一些“脏数据”或未被提交的数据潜在的可能被读取。

如果某个事务被滚回,那么应用了NOLOCK连接的数据读取操作将可以读取未提交的数据。这种类型的读取导致处理的不一致性会带来很多问题。这是你使用NOLOCK时应该了解的技巧。

作为一个负面影响,NOLOCK查询还可能带来读取“幻影”数据或读取在一个数据库读取事务中可以获得的但在另一个事务中可能被滚回的数据的风险。(我将在本系列文章的第二部分对这个负面影响进行详细说明。)

下面的例子展示了NOLOCK如何工作以及脏数据读取是如何产生的。在下面的脚本中,我用一个事务在SalesHistory数据表中插入一条记录。

 

  1. BEGIN TRANSACTION 
  2. INSERT INTO SalesHistory 
  3. (Product, SaleDate, SalePrice) 
  4. VALUES 
  5. ('PoolTable', GETDATE(), 500) 

这个事务仍旧是开放的,这意味着仍可以对插入数据表的记录上锁以阻止其它操作。在一个新的查询窗口中,运行下面的脚本,该脚本使用NOLOCK数据表提示返回SalesHistory数据表中的记录数。

  1. SELECT COUNT(*) FROM SalesHistory WITH(NOLOCK) 

返回记录数值为301。因为对SalesHistory数据表插入记录的事务还没有提交,所以我们可以撤销它。我通过使用下面的语句将事务滚回:

  1. ROLLBACK TRANSACTION 

该语句从SalesHistory数据表中删除前面插入的记录。现在我们运行前面运行的同样的SELECT语句。

  1. SELECT COUNT(*) FROM SalesHistory WITH(NOLOCK) 

这次返回记录数的值为300。我***次查询读记录的事务还没有提交,这就是一个脏数据读取。

READPAST

这是一个比NOLOCK较少使用的数据表提示。这个提示指明数据库引擎返回结果时忽略加锁的行或数据页。

这个数据表提示的优点和NOLOCK一样,在处理查询时不会发生阻塞。此外,读脏数据并不会出现在READPASTA中,因为不会返回锁定的记录。这个语句的缺点是,因为不返回锁定的记录,所以很难确定结果集或修改语句是否包含所有必须的记录。在你的应用中可能需要添加一些逻辑来确保最终包含所有必须的记录。

READPAST数据表提示的例子和NOLOCK的例子类似。我将使用一个事务来更新SalesHistory数据表中的一个记录。

 

  1. BEGIN TRANSACTION 
  2. UPDATE TOP(1) SalesHistory 
  3. SET SalePrice = SalePrice + 1 

因为我没有提交或回滚这个事务,所以添加在更新记录上的锁仍旧有效。在一个新的查询编辑窗口中,运行下面的脚本,该脚本对SalesHistory数据表使用READPAST统计表中的记录数。

 

  1. SELECT COUNT(*) 
  2. FROM SalesHistory WITH(READPAST) 

最初SalesHistory数据表中包含300条记录,UPDATE语句正锁定表中一条记录,所以上面使用READPAST的脚本返回结果为299条记录,这说明我要更新的记录被锁定,所以被REASPAST提示忽略。

原文链接:http://www.cnblogs.com/huanghai223/archive/2011/08/17/2143360.html

【编辑推荐】

  1. 养成一个SQL好习惯带来一笔大财富
  2. 客户的一次疏忽,DBA的一次噩梦
  3. 数据库的轮回
  4. 讲述MySQL索引和优化的故事
  5. 擦亮自己的眼睛去看SQL Server

 

 

责任编辑:艾婧 来源: 钻石眼泪的博客
相关推荐

2011-08-18 10:07:53

SQL Server脏NOLOCKREADPAST

2010-07-16 09:06:51

SQL Server数

2011-08-11 09:12:31

SQL Server nolock

2021-10-13 06:49:13

SQL Server优化

2021-04-20 19:21:50

脏读MySQL幻读

2022-04-27 07:32:02

脏读幻读不可重复读

2024-04-24 08:26:35

事务数据InnoDB

2019-03-21 09:06:00

数据库复读幻读

2023-02-02 11:53:44

nolock关键词SQLserver

2022-01-03 07:18:05

脏读幻读 MySQL

2023-11-01 14:13:00

MySQL事务隔离级别

2021-05-17 06:57:34

SQLServer数据库

2011-08-15 17:55:49

提取MapInfo地图SQL Server

2015-04-09 14:26:07

2024-04-19 08:18:47

MySQLSQL隔离

2022-11-15 08:35:00

SQLNOLOCK数据

2023-04-06 08:43:29

SQLWITH(NOLOCK

2011-08-30 11:04:30

链接查询内连接外连接

2010-07-02 10:47:20

SQL Server

2010-07-08 11:05:14

SQL Server数
点赞
收藏

51CTO技术栈公众号