日期:2014-05-19  浏览次数:20478 次

有关事务处理的多用户并发出现死锁的问题
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=@id

set   @iError   =   @@error   /*保存错误号*/

if   @iError=0
commite   tran   aaa
else
rollback   tran   aaa
GO


我现在发现一个问题,在多用户同时并发时,好象出现死锁,比如在查询分析器里输入“select   *   from   t_wh_billofdocument”,执行时,发现不动了好象出现死锁的状态,如果把“sql   server   服务器管理器”停止后,再重新启动时,就没事了,如果出现多用户并发而导致死锁打不开某个表时,该如何处理呢?

------解决方案--------------------
--1、首先,对于严重的错误,用@@error是捕获不到的,系统会自动终止执行,应该按类似如下格式:

ALTER PROCEDURE p_bs_product_save
@id int,
@code varchar (300) ,
@billcode varchar (300)
as
declare @iError int

--设置参数,如果一个事务中的任一一条SQL出错,整个事务都自动回滚
set xact_abort on

BEGIN TRANSACTION aaa

update t_wh_billofdocument set code=@code ,billcode=@billcode where id=@id

commite tran aaa
GO


--2、如楼上所述,设置关键字

--3、如果出现死锁,可以用kill清除掉这个进程,但应该从根本上避免死锁,应该从代码或实现方式上解决问题

--4、如果已经死锁,还要查询数据,用with (nolock)

如:

select * from 表名 with (nolock)


------解决方案--------------------
set xact_abort on 在事务处理时是必要的,
有主键的话代码上看不出问题,
但如果处在关联更新的时候(A\B 表)看看是否有先更新次序不同的事务,这样的事务在并发时很容易造成死锁
------解决方案--------------------
并发更新一个表的话如果并发多始终可能死锁,因为更新含有隐式游标,即使有索引也有冲突的可能,更改事务隔离级别会带来脏读等问题,,当发生死锁时回滚是没有用的,因为进程已经阻塞,所以最好的办法是不用事务或者从代码上避免死锁,可以参考哲学家用餐模型的算法

------解决方案--------------------
在多用户同时并发时,好象出现死锁
---------------------------------

LZ的存储过程其实很简单,这样的存储过程如果多用户并发就会出现死锁根本就没道理,
如果SqlServer是这样的产品也不会有几个人用了
是否真的死锁运行sp_lock就知道

所以LZ的问题应该是在updata语句上面,是不是更新要花很长时间?
我敢说LZ拿掉 BEGIN TRANSACTION 也会出现同样的问题,因为updata语句本身就有锁

最后还是建议用 sp_lock 观察一下


------解决方案--------------------
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!


------解决方案--------------------
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的条件
这样估计可以避免互相篡改的问题,你可以试下