不好意思,我的表述有问题,对同一表(不同行)的更新操作是指并发操作,而不是一个事务中存在对一个表的不同记录修改。
程序中select使用主键检索,再对结果集(只有一条纪录)进行update。

解决方案 »

  1.   

    select * from talbename with (rowlock)
    建议你看一下 SQLServer 2000 访问和更改关系数据->锁定->锁定提示
      

  2.   


     访问和更改关系数据  
    锁定提示
    可以使用 SELECT、INSERT、UPDATE 和 DELETE 语句指定表级锁定提示的范围,以引导 Microsoft® SQL Server™ 2000 使用所需的锁类型。当需要对对象所获得锁类型进行更精细控制时,可以使用表级锁定提示。这些锁定提示取代了会话的当前事务隔离级别。说明  SQL Server 查询优化器自动作出正确的决定。建议仅在必要时才使用表级锁定提示更改默认的锁定行为。禁止锁定级别反过来会影响并发。
    锁定提示 描述 
    HOLDLOCK 将共享锁保留到事务完成,而不是在相应的表、行或数据页不再需要时就立即释放锁。HOLDLOCK 等同于 SERIALIZABLE。 
    NOLOCK 不要发出共享锁,并且不要提供排它锁。当此选项生效时,可能会读取未提交的事务或一组在读取中间回滚的页面。有可能发生脏读。仅应用于 SELECT 语句。 
    PAGLOCK 在通常使用单个表锁的地方采用页锁。 
    READCOMMITTED 用与运行在提交读隔离级别的事务相同的锁语义执行扫描。默认情况下,SQL Server 2000 在此隔离级别上操作。 
    READPAST 跳过锁定行。此选项导致事务跳过由其它事务锁定的行(这些行平常会显示在结果集内),而不是阻塞该事务,使其等待其它事务释放在这些行上的锁。READPAST 锁提示仅适用于运行在提交读隔离级别的事务,并且只在行级锁之后读取。仅适用于 SELECT 语句。 
    READUNCOMMITTED 等同于 NOLOCK。 
    REPEATABLEREAD 用与运行在可重复读隔离级别的事务相同的锁语义执行扫描。  
    ROWLOCK 使用行级锁,而不使用粒度更粗的页级锁和表级锁。 
    SERIALIZABLE 用与运行在可串行读隔离级别的事务相同的锁语义执行扫描。等同于 HOLDLOCK。 
    TABLOCK 使用表锁代替粒度更细的行级锁或页级锁。在语句结束前,SQL Server 一直持有该锁。但是,如果同时指定 HOLDLOCK,那么在事务结束之前,锁将被一直持有。 
    TABLOCKX 使用表的排它锁。该锁可以防止其它事务读取或更新表,并在语句或事务结束前一直持有。 
    UPDLOCK 读取表时使用更新锁,而不使用共享锁,并将锁一直保留到语句或事务的结束。UPDLOCK 的优点是允许您读取数据(不阻塞其它事务)并在以后更新数据,同时确保自从上次读取数据后数据没有被更改。 
    XLOCK 使用排它锁并一直保持到由语句处理的所有数据上的事务结束时。可以使用 PAGLOCK 或 TABLOCK 指定该锁,这种情况下排它锁适用于适当级别的粒度。 
    例如,如果将事务隔离级别设置为 SERIALIZABLE,并且在 SELECT 语句中使用表级锁定提示 NOLOCK,则键范围锁通常用于维护不采用可串行事务。USE pubs
    GO
    SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
    GO
    BEGIN TRANSACTION
    SELECT au_lname FROM authors WITH (NOLOCK)
    GO生成的锁是:EXEC sp_lock
    GOspid dbid ObjId IndId Type Resource Mode Status 
    1 1 0 0 DB  S GRANT 
    6 1 0 0 DB  S GRANT 
    7 1 0 0 DB  S GRANT 
    8 4 0 0 DB  S GRANT 
    8 4 0 0 DB  S GRANT 
    8 4 117575457 0 TAB  Sch-S GRANT 
    9 4 0 0 DB  S GRANT 
    9 1 21575115 0 TAB  IS GRANT 
    SELECT object_name(117575457)
    GO
    -----------------------------
    authors引用 authors 唯一采用的锁是架构稳定性 (Sch-S) 锁。在这种情况下不能保证可串行性。
    请参见DELETEINSERTSELECTSET TRANSACTION ISOLATION LEVELUPDATE©1988-2000 Microsoft Corporation。保留所有权利。
      

  3.   

    我用过select * from T1 with(updlock) where...
    在vc程序中报错syntax error of with(owneraccess),不知道怎么回事?
    这个语句在analyzer中是正确的。
      

  4.   

    我明白你的意思,是通过循环来处理每一条记录,而且这个处理是事务性的,不能只完成一部分。
    但是这样的循环是很容易造成死锁的,最好能不用循环的方法,而改用一个或几个SQL语句来处理,但能不能做到要看你的处理逻辑,如果方便,不妨贴出你的处理要求和逻辑,我们帮你出出主意。
    还有一个能帮你缓解这个问题的方法是用存储过程,因为你现在每个循环都要查询一次,返回一条记录,再做一次或多次UPDATE,网络传输和SQL语句的编译花了大量时间,用存储过程能解决以上的弊端。最好能结合以上两个方法。
      

  5.   

    你为什么不行,我在delphi中就可以,
      

  6.   

    用可更新的分布式分区视图
    分区视图在一个或多个服务器间水平连接一组成员表中的分区数据,使数据看起来就象来自一个表。Microsoft® SQL Server™ 2000 区分本地分区视图和分布式分区视图。在本地分区视图中,所有的参与表和视图驻留在同一个 SQL Server 实例上。在分布式分区视图中,至少有一个参与表驻留在不同的(远程)服务器上。此外,SQL Server 2000 还区分可更新的分区视图和作为基础表只读复本的视图。分布式分区视图可用于实现数据库服务器联合体。联合体是一组分开管理的服务器,但它们相互协作分担系统的处理负荷。这种通过分区数据形成数据库服务器联合体的机制使您能够扩大一组服务器,以支持大型的多层 Web 站点的处理需要。有关更多信息,请参见设计联合数据库服务器。
      

  7.   

    事务大致是这样的:
    begin tran
    select * from table 1 .... (record 1)
    update record 1
    select * from table 2.... (record 2)
    update record 2
           ...
           ...
           ...
    select * from table n .... (record n)
    update record n
    commit tran
    现在的n值10-20之间吧,当然除了更新操作,还有其它逻辑(rollback等)。奇怪的是并行操作时,程序每次都是执行到同一个update处出现deadlock。
    第一次向大家请教,没想到这么受大家的关照,谢谢你们:)
      

  8.   

    update record set ....
    from 
    (select '1' as sign ,* from table1
    union
    select '2' as sign ,* from table2
    ...
    ...
    ..
    union
    select 'n' as sign ,* from table2
    ) as alltable,
    record 
    where record.rowid=sign
    //假设rowid是行数(用indetity)
      

  9.   

    因为我们不知道你系统的具体的情况,如使用人数,其他事务的影响,和vc application等,
    你只能sp_who,sp_lock与select * from master.dbo.syslock,
    企业管理器中的\管理\当前活动看,
    事件探查器trace,
    我也只能帮你到这步了。
    有事发mail, [email protected],
                                                        bye-bye
      

  10.   

    你说的事务情况和我估计的差不多,我的意思是也许不用一条一条循环着处理,而用一个UPDATE语句代替。
    比如,需要把一天的销售记录的总价改成等于单价*数量,你可以用循环一条一条处理,也可以用update 销售记录表 set 总价=单价*数量 where (时间在今天),这样处理效率能提高很多,而且不会死锁。
    也许以上例子举得太简单,也很不恰当,但希望你能明白我的意思。
      

  11.   

    我的情况和你不一样,但是也是在事务处理中时间长,碰到很多奇怪的问题(SQL6.5+WIN2000),比如:整个SQL服务被锁死,任何连接都不行,还有就是数据全部丢失,所有的表好像回到用SCRIPT新导入的样子。
      

  12.   

    程序原来的处理是建立记录集,在对记录集进行update。我也想直接update可能会减少死锁的可能性。程序中对记录集进行update的条件比较复杂,就放弃了。8992026你的意思我明白,不过我那事务里一般对一张表只update一条纪录。我曾把事务分成两个事务,就没有出现死锁的情况。还有一个问题,我怎么给你们分呢?