有这样的一个应用:
    SQL SERVER 2005
客户提交一个处理请求,放在请求表QQB里作为一条记录,等待被取出处理,处理程序在取出该记录处理时将其zt字段设为“正在处理”;如果该记录超时1分钟未被处理程序取出处理,另一个监控程序会将该条记录删除。问题是这样的,我担心监控程序的删除操作和处理程序的取出处理并更新操作会同时发生,在被删除的同时却又被取出处理,请问如下的操作会出现这样的情况吗?为了绝对避免这种情况出现,应该如何写程序?请高手指教,写出出具体的操作代码。请求表QQB,三个字段:
xh    int
tjsj  datetime  请求提交时间
zt    varchar(50)  记录处理的状态,未被处理时为null,取出处理时其值为“正在处理”处理程序:
......
update qqb set zt='正在处理' where xh=@xh
监控程序:
declare @tjsj datetime,@zt varchar(50)
select @tjsj=tjsj,@zt=zt where xh=@xh
if datediff(n,@tjsj,getdate())>1 and (zt is null)
   delete qqb where xh=@xh

解决方案 »

  1.   

    查询这个要处理的记录加UPDLOCK提示有偿支持
      

  2.   

    luckyrandom:    老大,你能说清楚点吗?请给予帮助
      

  3.   

    如果只有 处理程序 和 监控程序 这两个并发的话,处理起来比较简单。不需要使用任何事务和锁。只需要在处理程序中,将以下两句放在最前面即可:
    update qqb set zt='正在处理' where xh=@xh
    if @@rowcount = 0 return这样就可以保证只能被其中之一处理。
      

  4.   

    coleling:    为什么只有两个并发处理的时候可以这样处理,更多的并发时不能这样处理呢?
      

  5.   

    你先按照你的想法执行下,看有没有问题。一般的锁问题,SQL都会自动帮助你处理的。你不用担心。可以在更新的时候加上行锁定。也许能帮助你。。你多看看锁方面的知识。试试
      

  6.   

    就是个锁就行了。参考如下:
    1 如何锁一个表的某一行A 连接中执行SET TRANSACTION ISOLATION LEVEL REPEATABLE READbegin transelect * from tablename with (rowlock) where id=3waitfor delay '00:00:05'commit tranB连接中如果执行update tablename set colname='10' where id=3 --则要等待5秒update tablename set colname='10' where id<>3 --可立即执行2 锁定数据库的一个表SELECT * FROM table WITH (HOLDLOCK) 
    注意: 锁定数据库的一个表的区别SELECT * FROM table WITH (HOLDLOCK) 
    其他事务可以读取表,但不能更新删除SELECT * FROM table WITH (TABLOCKX) 
    其他事务不能读取表,更新和删除
      

  7.   

    如果只有 处理程序 和 监控程序 这两个并发的话,只需进行如下两步处理即可。--1.在处理程序中,将以下两句放在最前面:
    update qqb set zt='正在处理' where xh=@xh
    if @@rowcount = 0 return
    ......--修改监控程序,改成如下两种形式都可以:
    --1)加事务
    declare @tjsj datetime,@zt varchar(50)
    begin tran
    select @tjsj=tjsj,@zt=zt from qqb where xh=@xh
    if datediff(n,@tjsj,getdate())>1 and (zt is null)
      delete qqb where xh=@xh
    commit tran--2)压缩成一条语句
    delete qqb where xh=@xh and zt is null and datediff(n,tjsj,getdate()) > 1这样就可以绝对保证只能被其中之一处理。