快精灵印艺坊 您身边的文印专家
广州名片 深圳名片 会员卡 贵宾卡 印刷 设计教程
产品展示 在线订购 会员中心 产品模板 设计指南 在线编辑
 首页 名片设计   CorelDRAW   Illustrator   AuotoCAD   Painter   其他软件   Photoshop   Fireworks   Flash  

 » 彩色名片
 » PVC卡
 » 彩色磁性卡
 » 彩页/画册
 » 个性印务
 » 彩色不干胶
 » 明信片
   » 明信片
   » 彩色书签
   » 门挂
 » 其他产品与服务
   » 创业锦囊
   » 办公用品
     » 信封、信纸
     » 便签纸、斜面纸砖
     » 无碳复印纸
   » 海报
   » 大篇幅印刷
     » KT板
     » 海报
     » 横幅

在SQL SERVER 2005中解决死锁

数据库操作的死锁是不可避免的,本文并不打算讨论死锁如何产生,重点在于解决死锁,通过SQL 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
print \\\'end tran\\\'
SQL Server对付死锁的办法是牺牲掉其中的一个,抛出非常,并且回滚事务。在SQL Server 2000,语句一旦发生非常,T-SQL将不会继承运行,上面被牺牲的连接中, print \\\'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
我希望将来SQL Server 2005能够直接抛出原有非常,比如提供一个无参数的RaiseError。

因此方案有点臃肿,但将死锁问题封装到T-SQL中有助于明确职责,提高高层系统的清楚度。现在,对于DataAccess的代码,或许再也不需要考虑死锁问题了。
返回类别: 教程
上一教程: SQL SERVER 2005的30个最重要特点
下一教程: 数据库查询结果的动态排序(6)

您可以阅读与"在SQL SERVER 2005中解决死锁"相关的教程:
· SQL SERVER中死锁产生的原因及解决办法
· 总结 SQL Server 中死锁产生的原因及解决办法
· MICROSOFT SQL SERVER 2005 的 XML 最佳实施策略
· SQL Server 2005常见问题解答
· SQL SERVER中处理死锁
    微笑服务 优质保证 索取样品