有关事务处理的多用户并发出现死锁的问题
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的条件
这样估计可以避免互相篡改的问题,你可以试下