我使用的是SQL Server 2008 Enterprise。我想知道死锁问题是不是只由交叉依赖引起的(例如任务A在L1上有锁但在L2上等待锁,同时任务B在L2上有锁但在L1上等待锁)?是否还有其他导致死锁的原因和场景?
有没有其他方式会导致死锁--比如超时(一条S/I/D/U语句很长时间不返回,会返回死锁错误)或者长时间不能获取锁但不是交叉依赖导致的(比如任务C需要获取T表的锁,但另一个任务D获取T表的锁却没有释放锁,导致任务C长时间无法获取T表的锁)?
编辑1:如果多个线程同时执行此存储过程会导致死锁吗?
create PROCEDURE [dbo].[FooProc]
(
@Param1 int
,@Param2 int
,@Param3 int
)
AS
DELETE FooTable WHERE Param1 = @Param1
INSERT INTO FooTable
(
Param1
,Param2
,Param3
)
VALUES
(
@Param1
,@Param2
,@Param3
)
DECLARE @ID bigint
SET @ID = ISNULL(@@Identity,-1)
IF @ID > 0
BEGIN
SELECT IdentityStr FROM FooTable WHERE ID = @ID
END 先谢谢你,乔治
发布于 2010-06-01 15:03:36
死锁需要一个循环,在这个循环中,资源由等待其他进程持有的锁来释放锁的进程锁定。任何数量的进程都可以参与死锁,检测死锁的常规方法是获取锁的依赖关系图,并在该图中搜索循环。
你需要有一个死锁存在的循环。其他任何东西都只是一个等待释放锁的进程。查看哪些进程正在被其他进程阻塞的一种快速方法是sp_who2。
如果你想解决死锁问题,最好的方法是运行跟踪,拾取“死锁图”事件。这将允许您通过告诉您持有锁的查询来查看发生了什么。
发布于 2010-06-02 00:57:54
还有转换死锁:进程A和B都有对资源C的共享锁。两个进程都希望获得对C的独占锁。
即使两个进程只在一个资源上竞争,它们仍然可以在死锁中拥抱。下面的脚本再现了这样的场景。在一个选项卡中,运行以下命令:
CREATE TABLE dbo.Test ( i INT ) ;
GO
INSERT INTO dbo.Test
( i )
VALUES ( 1 ) ;
GO
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE ;
BEGIN TRAN
SELECT i
FROM dbo.Test ;
--UPDATE dbo.Test SET i=2 ;在此脚本完成后,我们有一个持有共享锁的未完成事务。在另一个选项卡中,让另一个连接在同一资源上拥有一个共享锁:
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE ;
BEGIN TRAN
SELECT i
FROM dbo.Test ;
--UPDATE dbo.Test SET i=2 ;这个脚本完成并呈现一个结果集,就像第一个脚本一样。现在,让我们突出显示并执行这两个选项卡中已注释的更新命令。要执行更新,每个连接都需要一个独占锁。两个连接都不能获得该排他锁,因为另一个连接持有共享锁。虽然这两个连接只在一种资源上竞争,但它们已经陷入了转换死锁:
消息1205,级别13,状态56,行1事务(进程ID 59)在与另一个进程的锁资源上发生死锁,并已被选为死锁牺牲品。重新运行交易记录。
还要注意,一个死锁中可能包含两个以上的连接。
发布于 2010-06-01 14:57:20
长时间不释放锁并不是死锁。
死锁是一种你永远不能前进的情况。这是由于2个(或更多)进程正在等待其他进程完成,但所有参与的进程都持有阻止其他进程继续的锁。
摆脱死锁的唯一方法是杀死进程来释放锁,因为无论您等待多长时间,它都不能自己完成。
https://stackoverflow.com/questions/2947725
复制相似问题