蝈蝈俊.net

-- 用随笔来记录自己的技术感触
随笔 - 673, 评论 - 4362, 引用 - 276

导航

关于

记录自己的技术心得

标签

每月存档

最新留言

  • Veolklmg
    Thanks funny site <a href=" http://www.wikio.com/user/mopoeo/bio ">f...
    by Veolklmg(匿名) on 2010/3/20 18:14:14
  • Vhdmlibq
    Gloomy tales <a href=" http://www.wikio.com/user/aqedacupar/bio ">an...
    by Vhdmlibq(匿名) on 2010/3/20 17:41:28
  • Hrxjzhbd
    good material thanks <a href=" http://www.wikio.com/user/aqedacupar/bio "&a...
    by Hrxjzhbd(匿名) on 2010/3/20 16:47:00
  • Hdzqmabf
    Punk not dead <a href=" http://www.wikio.com/user/akyuiigeq/bio ">i...
    by Hdzqmabf(匿名) on 2010/3/20 16:12:19
  • Cbxfrpuq
    Hello good day <a href=" http://www.wikio.com/user/akyuiigeq/bio ">p...
    by Cbxfrpuq(匿名) on 2010/3/20 15:15:03
  • re:学习笔记:7种结构型设计模式简单对比
    [url=http://www.he66.com]隔热材[/url][url=http://www.he66.com]防静电屏蔽袋[/url][url=http://www.he66.com]纯铝袋[...
    by as(匿名) on 2010/3/20 15:07:37
  • Sdnnhkur
    Cool site goodluck :) <a href=" http://www.wikio.com/user/gikihyfer/bio "&a...
    by Sdnnhkur(匿名) on 2010/3/20 14:42:33
  • Ixbrwhbq
    magic story very thanks <a href=" http://www.wikio.com/user/gikihyfer/bio "...
    by Ixbrwhbq(匿名) on 2010/3/20 13:47:16
  • Mtktzzls
    Best Site good looking <a href=" http://www.wikio.com/user/jufafakypokup/bio &qu...
    by Mtktzzls(匿名) on 2010/3/20 13:12:14
  • Ipjezvxt
    Jonny was here <a href=" http://www.wikio.com/user/jufafakypokup/bio "&...
    by Ipjezvxt(匿名) on 2010/3/20 12:16:42

广告

 

今天早上我在处理一个数据库死锁的异常时候,怡红公子给我的其中一个建议就是使用 NOLOCK 或者 READPAST 。我在使用后特整理有关 NOLOCK 和 READPAST的一些技术知识点到本篇博客:

对于非银行等严格要求事务的行业,搜索记录中出现或者不出现某条记录,都是在可容忍范围内,所以碰到死锁,应该首先考虑,我们业务逻辑是否能容忍出现或者不出现某些记录,而不是寻求对双方都加锁条件下如何解锁的问题。

NOLOCK 和 READPAST 都是处理查询、插入、删除等操作时候,如何应对锁住的数据记录。但是这时候一定要注意NOLOCK 和 READPAST的局限性,确认你的业务逻辑可以容忍这些记录的出现或者不出现:

 

简单来说:

NOLOCK 可能把没有提交事务的数据也显示出来.

READPAST 会把被锁住的行不显示出来 

不使用 NOLOCK 和 READPAST ,在 Select 操作时候则有可能报错误:事务(进程 ID **)与另一个进程被死锁在 锁 资源上,并且已被选作死锁牺牲品。

 

下面就来演示这个情况。

为了演示两个事务死锁的情况,我们下面的测试都需要在SQL Server Management Studio中打开两个查询窗口。保证事务不被干扰。

 

演示一 没有提交的事务,NOLOCK 和 READPAST处理的策略:

查询窗口一请执行如下脚本:

CREATE TABLE t1 (c1 int IDENTITY(1,1), c2 int)
go

BEGIN TRANSACTION
insert t1(c2) values(1)

 

在查询窗口一执行后,查询窗口二执行如下脚本:

select count(*) from t1 WITH(NOLOCK)
select count(*) from t1 WITH(READPAST)

 

结果与分析:

查询窗口二依次显示统计结果为: 1、0

查询窗口一的命令没有提交事务,所以 READPAST 不会计算没有提交事务的这一条记录,这一条被锁住了,READPAST 看不到;而NOLOCK则可以看到被锁住的这一条记录。

 

如果这时候我们在查询窗口二中执行:

select count(*) from t1 就会看到这个执行很久不能执行完毕,因为这个查询遇到了一个死锁。

 

清除掉这个测试环境,需要在查询窗口一中再执行如下语句:

ROLLBACK TRANSACTION
drop table t1

 

演示二:对被锁住的记录,NOLOCK 和 READPAST处理的策略

 

这个演示同样需要两个查询窗口。

请在查询窗口一中执行如下语句:

CREATE TABLE t2 (UserID int , NickName nvarchar(50))
go
insert t2(UserID,NickName) values(1,'郭红俊')
insert t2(UserID,NickName) values(2,'蝈蝈俊')
go

BEGIN TRANSACTION
update t2 set NickName = '蝈蝈俊.net' where UserID = 2

 

请在查询窗口二中执行如下脚本:

select * from t2 WITH(NOLOCK) where UserID = 2
select * from t2 WITH(READPAST) where UserID = 2

 

结果与分析:

查询窗口二中, NOLOCK 对应的查询结果中我们看到了修改后的记录,READPAST对应的查询结果中我们没有看到任何一条记录。

清除测试环境方法参看演示一。

 

参考资料:

Using NOLOCK and READPAST table hints in SQL Server

http://topic.csdn.net/t/20060905/14/4999881.html

打印 | 张贴于 2007-05-31 13:11:00 | Tag:数据库开发管理心得

留言反馈

#SQL 一些语句 编辑
随机排序:orderbynewid() 时间比较:如比较日:Datediff(dd,joindate,getdate())=0
2007-11-22 11:38:00 | [匿名:尚尚]
#回复: 在查询语句中使用 NOLOCK 和 READPAST 编辑
网上找的,看那里死锁的存储过程

if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[sp_who_lock]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[sp_who_lock]
GO
/***************************************************************************
// 创建 : fengyu 邮件 : maggiefengyu@tom.com 日期 :2004-04-30
// 修改 : 从http://www.csdn.net/develop/Read_Article.asp?id=26566学习到并改写
// 说明 : 查看数据库里阻塞和死锁情况
***************************************************************************/
use master
go
create procedure sp_who_lock
as
begin
declare @spid int,@bl int,
@intTransactionCountOnEntry int,
@intRowcount int,
@intCountProperties int,
@intCounter int

create table #tmp_lock_who (
id int identity(1,1),
spid smallint,
bl smallint)

IF @@ERROR<>0 RETURN @@ERROR

insert into #tmp_lock_who(spid,bl) select 0 ,blocked
from (select * from sysprocesses where blocked>0 ) a
where not exists(select * from (select * from sysprocesses where blocked>0 ) b
where a.blocked=spid)
union select spid,blocked from sysprocesses where blocked>0

IF @@ERROR<>0 RETURN @@ERROR

-- 找到临时表的记录数
select @intCountProperties = Count(*),@intCounter = 1
from #tmp_lock_who

IF @@ERROR<>0 RETURN @@ERROR

if @intCountProperties=0
select '现在没有阻塞和死锁信息' as message

-- 循环开始
while @intCounter <= @intCountProperties
begin
-- 取第一条记录
select @spid = spid,@bl = bl
from #tmp_lock_who where Id = @intCounter
begin
if @spid =0
select '引起数据库死锁的是: '+ CAST(@bl AS VARCHAR(10)) + '进程号,其执行的SQL语法如下'
else
select '进程号SPID:'+ CAST(@spid AS VARCHAR(10))+ '被' + '进程号SPID:'+ CAST(@bl AS VARCHAR(10)) +'阻塞,其当前进程执行的SQL语法如下'
DBCC INPUTBUFFER (@bl )
end

-- 循环指针下移
set @intCounter = @intCounter + 1
end


drop table #tmp_lock_who

return 0
end
2007-10-30 10:52:00 | [匿名:郭红俊]
#回复: 在查询语句中使用 NOLOCK 和 READPAST 编辑
2007-10-19 11:49:00 | [匿名:mayf_like]
#SqlServer Tips 收集 编辑
随机排序:orderbynewid() 时间比较:如比较日:Datediff(dd,joindate,getdate())=0
2007-10-17 04:26:00 | [匿名:梦想依旧]
#回复: 在查询语句中使用 NOLOCK 和 READPAST 编辑
非常感谢指正。^&^
2007-06-01 08:55:00 | [匿名:ghj1976]
#回复: 在查询语句中使用 NOLOCK 和 READPAST 编辑
NOLOCK 对应的查询结果中我们看到了修改后的记录,READPAST对应的查询结果中我们没有看到任何一条记录。
2007-06-01 00:26:00 | [匿名:db661音乐站]
#回复: 在查询语句中使用 NOLOCK 和 READPAST 编辑
死锁一般是在两个transaction同时操作一个数据, 而又没有对它加锁造成的吧...
2007-05-31 16:14:00 | [匿名:VincentChen]
#回复: 在查询语句中使用 NOLOCK 和 READPAST 编辑
顺便说一下,死锁的原因很可能跟索引有关。只是我没连上你的数据库,没法深究。
第二,你演示的不叫死锁,那是阻塞,block
2007-05-31 15:50:00 | [匿名:怡红公子]

发表留言

标题
姓名
邮件
主页
留言 

Powered by: Joycode.MVC引擎 0.5.2.0