如何解决c3p0数据库连接池死锁问题

如何解决c3p0数据库连接池死锁问题,第1张

当两个用户(或会话)具有不同对象的锁,并且每个用户需要另一个对象的锁时,就会出现死锁。每个用户都等待另一个用户释放他的锁。当两个连接陷入死锁时,Microsoft? SQL Server? 会进行检测。其中一个连接被选作死锁牺牲品。该连接的事务回滚,同时应用程序收到错误。

如果死锁变成单个公用事件,而且它们的回滚造成过多的性能降级,那么就需要再次进行深入彻底的调查。使用跟踪标记 1204.例如,下面的命令从命令提示符启动 SQL Server,并启用跟踪标记 1204:

c:\mssql\binn\sqlservr -T1204

现在所有消息都会显示在启动 SQL Server 的控制台屏幕上和错误日志中。

使用分布式事务时,也可能发生死锁。阻塞

任何基于锁的并发系统都不可避免地具有可能在某些情况下发生阻塞的特征。当一个连接控制了一个锁,而另一个连接需要冲突的锁类型时,将发生阻塞。其结果是强制第二个连接等待,或在第一个连接上阻塞。

在本主题中,术语"连接"是指数据库的单个登录会话。每个连接都作为系统进程 ID (SPID) 出现。尽管每一个 SPID 一般都不是单独的进程上下文,但这里常常用来指一个进程。更确切的说,每个 SPID 都是由服务器资源和数据结构(为给定客户单个连接的请求提供服务)组成。单个客户应用程序可能有一个或多个连接。就 SQL Server 而言,从单个客户机上的单个客户应用程序来的多个连接和从多个客户应用程序或多个客户机来的多个连接是没有区别的。不管是来自同一应用程序还是来自两台不同客户机上单独的应用程序,一个连接都可以阻塞另一个连接。

数据库 *** 作的死锁是不可避免的,本文并不打算讨论死锁如何产生,重点在于解决死锁,通过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


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/sjk/9945907.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-03
下一篇 2023-05-03

发表评论

登录后才能评论

评论列表(0条)

保存