CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
不看会后悔的Windows XP之经验谈 简单快捷DIY实用家庭影院
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  VB >  数据库(包含打印,安装,报表)

SQL Server 版人气不旺,来这里再发一次,有关行级锁的问题,新手向大家请教了

楼主jjkk168(老加班的人--好好学习,天天吃饭)2006-04-04 13:41:38 在 VB / 数据库(包含打印,安装,报表) 提问

本人在处理并发操作的时候碰到了问题  
   
  有表结构如下  
   
  Code(varchar)                     Content(text)  
  001                                         **********  
  002                                         **********  
  003                                         **********  
   
   
  其中Content字段存放的是一设计好的XML文件,到时候只需要将其读出写入XML中,应用程序就可以直接处理了。  
   
  但目前想实现的情况如下:  
  当用户正在读取Code='001'的时候,就想自动将001该行锁定,其他用户可读,但不可写,并且需要反馈出哪个用户用的哪台主机正在进行读操作  
   
  问题  
  1、需要行锁,如果使用Select   Code,Content   From   Table1   with   (ROWLOCK)   Where   Code   =   '001',这样操作是否正确?(想实现该行不能进行写操作,如果有写入的操作,就报错)  
  2、如何解锁  
  3、如何读取出某一行正被哪个用户进行操作?  
   
   
  谢谢!  
   
   
  原贴位置:  
  http://community.csdn.net/Expert/topic/4661/4661107.xml?temp=.6548883 问题点数:200、回复次数:11Top

1 楼Modest(塞北雪貂)·(偶最欣赏楼主的分)回复于 2006-04-04 13:55:40 得分 0

除了行锁定外我只想到一个办法,就是给数据库加几个字段LockUserID、Locked、LockTime,select的同时更新这些记录的LockUserID、Locked、LockTime,在规定的时限内只有LockUserID可以更新。  
  所有用户select前先将LockTime和getdate()比较,超过时限的先解锁,再select资料出来。Top

2 楼Modest(塞北雪貂)·(偶最欣赏楼主的分)回复于 2006-04-04 13:56:05 得分 90

--锁定记录,只允许单用户修改的例子:  
  --创建测试环境  
  --创建测试表--部门表  
  create   table   部门(departmentid   int,name   varchar(10))  
  --记录锁定表  
  create   table   lock(departmentid   int,dt   datetime)  
  go  
  --因为函数中不可以用getdate,所以用个视图,得到当前时间  
  create   view   v_getdate   as   select   dt=getdate()  
  go  
  --创建自定义函数,判断记录是否锁定  
  create   function   f_chk(@departmentid   int)  
  returns   bit  
  as  
  begin  
  declare   @re   bit,@dt   datetime  
  select   @dt=dt   from   v_getdate  
  if   exists(select   1   from   lock   where   departmentid=@departmentid  
  and   datediff(minute,dt,@dt)<5)     --锁的超时时间为5分钟  
  set   @re=1  
  else  
  set   @re=0  
  return(@re)  
  end  
  go  
  --数据处理测试,操作记录3  
  if   dbo.f_chk(3)=1  
  print   '记录被锁定'  
  else  
  begin  
  begin   tran  
  insert   into   lock   values(3,getdate())  
  update   部门   set   name='A'   where   departmentid=3  
  delete   from   lock   where   departmentid=3  
  commit   tran  
  end  
  --删除测试环境  
  drop   table   部门  
  drop   view   v_getdate  
  drop   function   f_chkTop

3 楼unsigned(僵哥(发站内消息,请附上链接或问题说明,否则不予回复))回复于 2006-04-04 14:21:01 得分 0

1、需要行锁,如果使用Select   Code,Content   From   Table1   with   (ROWLOCK)   Where   Code   =   '001',这样操作是否正确?(想实现该行不能进行写操作,如果有写入的操作,就报错)  
  >>如此最好帶UDPLOCK,即更新鎖,則在你的事務完成之後該鎖定一直有效  
  2、如何解锁  
  >>鎖是相對事務而言的,所以正常情況下是當你的事務完成(包括提交或者回滾)了就解鎖了,若異常也可以使用Kill   PID來解鎖,相關請查閱Kill命隻  
  3、如何读取出某一行正被哪个用户进行操作?  
  >>這個有點太複雜須查詢相關的系統表,曾經在一國外的站點上面有看到一個別人寫的存儲過程,但是系統重裝後沒有了^_^Top

4 楼unsigned(僵哥(发站内消息,请附上链接或问题说明,否则不予回复))回复于 2006-04-04 14:21:43 得分 0

>>如此最好帶UDPLOCK,即更新鎖,則在你的事務完成之後該鎖定一直有效  
  -------------  
  應該是事務完成之前一直有效.Top

5 楼jjkk168(老加班的人--好好学习,天天吃饭)回复于 2006-04-04 18:02:08 得分 0

不是太明白,再顶Top

6 楼unsigned(僵哥(发站内消息,请附上链接或问题说明,否则不予回复))回复于 2006-04-04 18:57:34 得分 0

connction.BegeinTrans  
  try  
        connection.Execute('Select   Code,Content   From   Table1   with   (ROWLOCK,UDPLOCK,HOLDLOCK)   Where   Code   =   ''001''');  
  ...  
        connction.CommitTrans;  
  except  
        connection.RollBackTrans;  
  end;Top

7 楼unsigned(僵哥(发站内消息,请附上链接或问题说明,否则不予回复))回复于 2006-04-04 18:59:16 得分 0

倒,不小心把这看作Delphi了  
   
  connection.BeginTrans  
  on   error   goto   errhandle  
  call   connection.execute("Select   Code,Content   From   Table1   with   (ROWLOCK,UDPLOCK,HOLDLOCK)   Where   Code   =   '001'")  
  ...  
  connection.CommitTrans  
  exit   sub/function  
  errhandle:  
        connection.rollbacktrans  
  end   sub/functionTop

8 楼jjkk168(老加班的人--好好学习,天天吃饭)回复于 2006-04-04 23:23:35 得分 0

谢谢!  
   
  那么需要解锁就只需要rollback   trans就行了?  
   
   
  还有,能否帮我查出是哪个客户端正在锁定该行的代码?谢谢!Top

9 楼unsigned(僵哥(发站内消息,请附上链接或问题说明,否则不予回复))回复于 2006-04-04 23:57:10 得分 0

并不能知道是哪个客户端在锁定,除非你有登记各客户端连接在SQL当中相应的PID,最多只能查到哪个表的哪条记录被锁定Top

10 楼jjkk168(老加班的人--好好学习,天天吃饭)回复于 2006-04-05 11:04:03 得分 0

我可以做到登记PID,但如何查到这个表中的这一行记录被哪个PID锁定?谢谢Top

11 楼unsigned(僵哥(发站内消息,请附上链接或问题说明,否则不予回复))回复于 2006-04-05 13:30:42 得分 110

不好意思是SPID  
  當前連接的SPID可以使用:select   @@SPID獲得  
   
  不好意思,剛查了一下資料.  
  對於鎖定的行,系統是資源來記錄,而並不記錄具體的行,所以無法知道鎖定到哪一行.  
   
  create   procedure   sp_lock2  
  @spid1   int   =   NULL,             /*   server   process   id   to   check   for   locks   */  
  @spid2   int   =   NULL               /*   other   process   id   to   check   for   locks   */  
  as  
  set   nocount   on  
  /*  
  **   Show   the   locks   for   both   parameters.  
  */  
  declare   @objid   int,  
        @indid   int,  
        @dbid   int,  
        @string   Nvarchar(255)  
   
  CREATE   TABLE   #locktable  
        (  
        spid               smallint  
        ,loginname   nvarchar(20)  
        ,hostname     nvarchar(30)  
        ,dbid             int  
        ,dbname         nvarchar(20)  
        ,ObjOwner     nvarchar(128)  
        ,objid           int  
        ,ObjName       nvarchar(128)  
        ,indid           int  
        ,IndName       nvarchar(128)  
        ,Type             nvarchar(4)  
        ,Resource     nvarchar(16)  
        ,Mode             nvarchar(8)  
        ,Status         nvarchar(5)  
        )  
   
  if   @spid1   is   not   NULL  
  begin  
        INSERT   #locktable  
              (  
              spid  
              ,loginname  
              ,hostname  
              ,dbid  
              ,dbname  
              ,ObjOwner  
              ,objid  
              ,ObjName  
              ,indid  
              ,IndName  
              ,Type  
              ,Resource  
              ,Mode  
              ,Status  
              )  
        select   convert   (smallint,   l.req_spid)  
              ,coalesce(substring   (s.loginame,   1,   20),'')  
              ,coalesce(substring   (s.hostname,   1,   30),'')  
              ,l.rsc_dbid  
              ,substring   (db_name(l.rsc_dbid),   1,   20)  
              ,''  
              ,l.rsc_objid  
              ,''  
              ,l.rsc_indid  
              ,''  
              ,substring   (v.name,   1,   4)  
              ,substring   (l.rsc_text,   1,   16)  
              ,substring   (u.name,   1,   8)  
              ,substring   (x.name,   1,   5)  
        from   master.dbo.syslockinfo   l,  
              master.dbo.spt_values   v,  
              master.dbo.spt_values   x,  
              master.dbo.spt_values   u,  
              master.dbo.sysprocesses   s  
        where   l.rsc_type   =   v.number  
        and       v.type   =   'LR'  
        and       l.req_status   =   x.number  
        and       x.type   =   'LS'  
        and       l.req_mode   +   1   =   u.number  
        and       u.type   =   'L'  
        and       req_spid   in   (@spid1,   @spid2)  
        and       req_spid   =   s.spid  
  end  
  /*  
  **   No   parameters,   so   show   all   the   locks.  
  */  
  else  
  begin  
        INSERT   #locktable  
              (  
              spid  
              ,loginname  
              ,hostname  
              ,dbid  
              ,dbname  
              ,ObjOwner  
              ,objid  
              ,ObjName  
              ,indid  
              ,IndName  
              ,Type  
              ,Resource  
              ,Mode  
              ,Status  
              )  
        select   convert   (smallint,   l.req_spid)  
              ,coalesce(substring   (s.loginame,   1,   20),'')  
              ,coalesce(substring   (s.hostname,   1,   30),'')  
              ,l.rsc_dbid  
              ,substring   (db_name(l.rsc_dbid),   1,   20)  
              ,''  
              ,l.rsc_objid  
              ,''  
              ,l.rsc_indid  
              ,''  
              ,substring   (v.name,   1,   4)  
              ,substring   (l.rsc_text,   1,   16)  
              ,substring   (u.name,   1,   8)  
              ,substring   (x.name,   1,   5)  
        from   master.dbo.syslockinfo   l,  
              master.dbo.spt_values   v,  
              master.dbo.spt_values   x,  
              master.dbo.spt_values   u,  
              master.dbo.sysprocesses   s  
        where   l.rsc_type   =   v.number  
        and       v.type   =   'LR'  
        and       l.req_status   =   x.number  
        and       x.type   =   'LS'  
        and       l.req_mode   +   1   =   u.number  
        and       u.type   =   'L'  
        and       req_spid   =   s.spid  
        order   by   spid  
  END  
  DECLARE   lock_cursor   CURSOR  
  FOR   SELECT   dbid,   objid,   indid   FROM   #locktable  
      WHERE   Type   <>'DB'   and   Type   <>   'FIL'  
   
  OPEN   lock_cursor  
  FETCH   NEXT   FROM   lock_cursor   INTO   @dbid,   @objid,   @indid  
  WHILE   @@FETCH_STATUS   =   0  
        BEGIN  
   
        SELECT   @string   =  
              'USE   '   +   db_name(@dbid)   +   char(13)  
              +   'update   #locktable   set   ObjName   =   name,   ObjOwner   =   USER_NAME(uid)'  
              +   '   from   sysobjects   where   id   =   '   +   convert(varchar(32),@objid)  
              +   '   and   objid   =   '   +   convert(varchar(32),@objid)  
              +   '   and   dbid   =   '   +   convert(varchar(32),@dbid)  
   
        EXECUTE   (@string)  
   
        SELECT   @string   =  
              'USE   '   +   db_name(@dbid)   +   char(13)  
              +   'update   #locktable   set   IndName   =   i.name   from   sysindexes   i   '  
              +   '   where   i.id   =   '   +   convert(varchar(32),@objid)  
              +   '   and   i.indid   =   '   +   convert(varchar(32),@indid)  
              +   '   and   objid   =   '   +   convert(varchar(32),@objid)  
              +   '   and   dbid   =   '   +   convert(varchar(32),@dbid)  
              +   '   and   #locktable.indid   =   '   +   convert(varchar(32),@indid)  
   
        EXECUTE   (@string)  
   
        FETCH   NEXT   FROM   lock_cursor   INTO   @dbid,   @objid,   @indid  
        END  
  CLOSE   lock_cursor  
  DEALLOCATE   lock_cursor  
   
  SELECT   *   FROM   #locktable  
  --return   (0)  
  --   END   sp_lock2  
  Top

相关问题

关键词

得分解答快速导航

  • 帖主:jjkk168
  • Modest
  • unsigned

相关链接

  • Visual Basic类图书
  • Visual Basic类源码下载

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
北京创新乐知广告有限公司 版权所有, 京 ICP 证 070598 号
世纪乐知(北京)网络技术有限公司 提供技术支持
Copyright © 2000-2008, CSDN.NET, All Rights Reserved
GongshangLogo