Server
2005,
现在似乎有了一种新的解决办法。
将下面的SQL语句放在两个不同的连接里面,并且在5秒内同时执行,将会发生死锁。
use
Northwind
begin
tran
insert
into
Orders(CustomerId)
values(@#ALFKI@#)
waitfor
delay
@#00:00:05@#
select
*
from
Orders
where
CustomerId
=
@#ALFKI@#
commit
@#end
tran@#
SQL
Server对付死锁的办法是牺牲掉其中的一个,抛出异常,并且回滚事务。在SQL
Server
2000,语句一旦发生异常,T-SQL将不会继续运行,上面被牺牲的连接中,
@#end
tran@#语句将不会被运行,所以我们很难在SQL
Server
2000的T-SQL中对死锁进行进一步的处理。
现在不同了,SQL
Server
2005可以在T-SQL中对异常进行捕获,这样就给我们提供了一条处理死锁的途径:
下面利用的try
...
catch来解决死锁。
SET
XACT_ABORT
ON
declare
@r
int
set
@r
=
1
while
@r
<=
3
begin
begin
tran
begin
try
insert
into
Orders(CustomerId)
values(@#ALFKI@#)
waitfor
delay
@#00:00:05@#
select
*
from
Orders
where
CustomerId
=
@#ALFKI@#
commit
break
end
try
begin
catch
rollback
waitfor
delay
@#00:00:03@#
set
@r
=
@r
+
1
continue
end
catch
end
解决方法当然就是重试,但捕获错误是前提。rollback后面的waitfor不可少,发生冲突后需要等待一段时间,@retry数目可以调整以应付不同的要求。
但是现在又面临一个新的问题:
错误被掩盖了,一但问题发生并且超过3次,异常却不会被抛出。SQL
Server
2005
有一个RaiseError语句,可以抛出异常,但却不能直接抛出原来的异常,所以需要重新定义发生的错误,现在,解决方案变成了这样:
declare
@r
int
set
@r
=
1
while
@r
<=
3
begin
begin
tran
begin
try
insert
into
Orders(CustomerId)
values(@#ALFKI@#)
waitfor
delay
@#00:00:05@#
select
*
from
Orders
where
CustomerId
=
@#ALFKI@#
commit
break
end
try
begin
catch
rollback
waitfor
delay
@#00:00:03@#
set
@r
=
@r
+
1
continue
end
catch
end
if
ERROR_NUMBER()
<>
0
begin
declare
@ErrorMessage
nvarchar(4000)
declare
@ErrorSeverity
int
declare
@ErrorState
int
select
@ErrorMessage
=
ERROR_MESSAGE(),
@ErrorSeverity
=
ERROR_SEVERITY(),
@ErrorState
=
ERROR_STATE()
raiserror
(@ErrorMessage,
@ErrorSeverity,
@ErrorState
)
end
多线程是很容易造成死锁,一般情况下死锁都是因为并发 *** 作引起的。我不懂JAVA,但死锁这个问题每种开发工具和数据库都会碰到.解决办法是:1、程序方面优化算法(如有序资源分配法、银行算法等),在一个程序里,能不用多线程更新同一张数据库表 尽量不要用,如果要用,其避免死锁的算法就很复杂。
2、数据库方面设置等待超时时间
3、发生死锁后直接KILL掉数据库进程
建议:1、使用事件探查器,跟踪一下SQL在死锁之前执行了哪些SQL语句
2、多数死锁是因为程序没有经过严格的测试造成的
3、少部分原因是因为触发器嵌套造成的,SQL有内部机制,当嵌套到一定的层级,就自动终止掉相关的进程
愿早日解决问题
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)