sqlserver2000,我在存储过程增加了事务处理,比如下面语句ALTER PROCEDURE p_bs_product_save
@id int,
@code varchar (300) ,
@billcode varchar (300)
as
declare @iError int
BEGIN TRANSACTION aaa
update t_wh_billofdocument set code=@code ,billcode=@billcode where id=@idset @iError = @@error /*保存错误号*/if @iError=0
commite tran aaa
else
rollback tran aaa
GO
我现在发现一个问题,在多用户同时并发时,好象出现死锁,比如在查询分析器里输入“select * from t_wh_billofdocument”,执行时,发现不动了好象出现死锁的状态,如果把“sql server 服务器管理器”停止后,再重新启动时,就没事了,如果出现多用户并发而导致死锁打不开某个表时,该如何处理呢?

解决方案 »

  1.   

    试下更改隔离级别ALTER PROCEDURE p_bs_product_save
    @id int,
    @code varchar (300) ,
    @billcode varchar (300)
    as
    declare @iError intSET TRANSACTION ISOLATION LEVEL READ UNCOMMITTEDBEGIN TRANSACTION aaa
    update t_wh_billofdocument set code=@code ,billcode=@billcode where id=@idset @iError = @@error /*保存错误号*/if @iError=0
    commite tran aaa
    else
    rollback tran aaa
    GO
      

  2.   

    --1、首先,对于严重的错误,用@@error是捕获不到的,系统会自动终止执行,应该按类似如下格式:ALTER PROCEDURE p_bs_product_save
    @id int,
    @code varchar (300) ,
    @billcode varchar (300)
    as
    declare @iError int--设置参数,如果一个事务中的任一一条SQL出错,整个事务都自动回滚
    set xact_abort onBEGIN TRANSACTION aaaupdate t_wh_billofdocument set code=@code ,billcode=@billcode where id=@idcommite tran aaa
    GO
    --2、如楼上所述,设置关键字--3、如果出现死锁,可以用kill清除掉这个进程,但应该从根本上避免死锁,应该从代码或实现方式上解决问题--4、如果已经死锁,还要查询数据,用with (nolock)如:select * from 表名 with (nolock)
      

  3.   

    to wangtiecheng:
    如果出现死锁,要避免它,应该从代码或实现方式上解决问题,是不是说把我写的代码改
    成你写的代码,会不会避免?比如你建议这样写:
    ALTER PROCEDURE p_bs_product_save
    @id int,
    @code varchar (300) ,
    @billcode varchar (300)
    as
    declare @iError int--设置参数,如果一个事务中的任一一条SQL出错,整个事务都自动回滚
    set xact_abort onBEGIN TRANSACTION aaaupdate t_wh_billofdocument set code=@code ,billcode=@billcode where id=@idcommite tran aaa
    GO
      

  4.   

    ALTER PROCEDURE p_bs_product_save
    @id int,
    @code varchar (300) ,
    @billcode varchar (300)
    as
    假如我这样写
    declare @iError int--设置参数,如果一个事务中的任一一条SQL出错,整个事务都自动回滚
    set xact_abort onBEGIN TRANSACTION aaaupdate t_wh_billofdocument set code=@code ,billcode=@billcode where id=@idcommite tran aaa
    GO如果有出错,就会整个事务都自动回滚,我想在代码里加一个回滚的提示,比如“当前数据保存不成功”,在这个代码里如何加?
      

  5.   

    set xact_abort on 在事务处理时是必要的,
    有主键的话代码上看不出问题,
    但如果处在关联更新的时候(A\B 表)看看是否有先更新次序不同的事务,这样的事务在并发时很容易造成死锁
      

  6.   

    这个存储过程应该没问题.
    还是查找下为什么锁吧.
    管理->当前活动->用户  看看锁和和阻塞对象都在运行什么sql语句.看看是否逻辑顺序混乱造成的.
      

  7.   

    to wangtiecheng:
    在代码里加一个回滚的提示,比如“当前数据保存不成功”,能不能直接在存储过程里写?如果行的话,如何写
      

  8.   

    可能性很小dbcc checkdb 检查一下数据库内部是否有分配错误或一致性错误
      

  9.   

    SQL Server 2005的错误处理机制改进了许多,可以根据错误类型不同,提示自己的错误信息
      

  10.   

    to wangtiecheng:
    --1、首先,对于严重的错误,用@@error是捕获不到的,系统会自动终止执行,应该按类似如下格式:ALTER PROCEDURE p_bs_product_save
    @id int,
    @code varchar (300) ,
    @billcode varchar (300)
    as
    declare @iError int--设置参数,如果一个事务中的任一一条SQL出错,整个事务都自动回滚
    set xact_abort onBEGIN TRANSACTION aaaupdate t_wh_billofdocument set code=@code ,billcode=@billcode where id=@idcommite tran aaa
    GO
    我的问题:
    (1)、如果有错误时就回滚时不用加上rollback tran aaa,难道只加上set xact_abort on就可以了
      

  11.   

    那就不用加rollback tran aaa了
      

  12.   

    在多用户同时并发时,好象出现死锁
    ---------------------------------LZ的存储过程其实很简单,这样的存储过程如果多用户并发就会出现死锁根本就没道理,
    如果SqlServer是这样的产品也不会有几个人用了
    是否真的死锁运行sp_lock就知道所以LZ的问题应该是在updata语句上面,是不是更新要花很长时间?
    我敢说LZ拿掉 BEGIN TRANSACTION 也会出现同样的问题,因为updata语句本身就有锁最后还是建议用 sp_lock 观察一下
      

  13.   


    BEGIN TRANSACTION aaaupdate t_wh_billofdocument set code=@code ,billcode=@billcode where id=@idcommite tran aaa
    这样的代码,我觉得是没有必要用事务.浪费两行代码
      

  14.   

    update不用事务更容易死锁  汗
      

  15.   

    我的问题:
    (1)、如果有错误时就回滚时不用加上rollback tran aaa,难道只加上set xact_abort on就可以了---------------------------------------------
    设置了set xact_abort on,不用加rollback tran aa,如果出错,就会自动回滚。当然,如果你想在每执行一句SQL后,用@@error判断一下,给出自己的错误提示信息,这样没有问题。但是一旦出现很严重的错促,这时判断@@error的代码根本不会执行,系统自动终止执行,自动回滚事务
      

  16.   

    用sp_lock查一下,看一下你的update语句是不是执行时间太长
      

  17.   

    本人也正在想解决这个问题,我是数据库是SYSBASE,同样的代码在DB2和ORACLE下都是好的。
      

  18.   

    1.我们先看事务的简要的定义:
    A transaction is a logical unit of work made up of a series of statements (selects, 
    inserts, updates, or deletes). 
    那么提供的过程中只有且仅有一个UPDATE语句,这个语句它就是一个unit。如果确实是这样的话
    (只有一个UPDATE语句)那么过程中定义的事务(aaa)就显得多余了,不需要用显式的事务来控制
    它,sql server 自己会处理的。
    2.楼主,对一些基本的概念还不十分清楚,所以再描述问题的时候都是不确定的口吻。
    可以了解一下基本的概念如:什么阻塞?什么是死锁,有那些类型?两者有何不同,什么情况
    下前者后发展成后者?如何监测识别阻塞和死锁?等等。把概念弄清楚了,再来分析你所遇到的
    问题,自己就应该能搞定了。Good luck!
      

  19.   

    hb_gx(高升) ( ) 信誉:100 说的很对我觉得要么你不用事务,关于互相篡改数据的问题,可以增加一个ROWVERSION列来控制
    比如给你的T_WH_BILLOFDOCUMENT 增加一个列ROWCONTROL类型为ROWVERSION.
    select @rowversion=rowversion from t_wh_billofdocument where id=@id
    update t_wh_billofdocument set code=@code ,billcode=@billcode where id=@id and rowcontrol=@rowversion
    以后在SELECT查询中都加上ROWCONTROL=@ROWCONTROL的条件
    这样估计可以避免互相篡改的问题,你可以试下