如果没有定义任何事务明确,是否会发生死锁?

时间:2018-03-24 16:31:26

标签: sql-server-2008 deadlock

如果我们没有事务块(SQL Server 2008)

BEGIN TRAN
END TRAN

DELETEUPDATEINSERTINSERT SELECT

是否可能陷入僵局?如果是的话,你能举个例子吗?

1 个答案:

答案 0 :(得分:1)

是的,即使没有明确的事务,也可能在2个不同的会话之间发生死锁。下面的示例脚本在我的测试框上生成死锁。

--prep script
CREATE TABLE dbo.Example(
      Col1 int NOT NULL CONSTRAINT PK_Example PRIMARY KEY
    , Col2 int NOT NULL
    , Col3 int NOT NULL
    , Col4 char(2000) NULL
    );
GO
WITH 
     t10 AS (SELECT n FROM (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) t(n))
    ,t1k AS (SELECT 0 AS n FROM t10 AS a CROSS JOIN t10 AS b CROSS JOIN t10 AS c)
    ,t1m AS (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS num FROM t1k AS a CROSS JOIN t1k AS b CROSS JOIN t1k AS c)
INSERT INTO dbo.Example(Col1, Col2, Col3)
SELECT num, num % 100, num % 150
FROM t1m
WHERE num <= 1000000;
GO

CREATE INDEX idx_Col2 ON dbo.Example(Col2);
CREATE INDEX idx_Col3 ON dbo.Example(Col3);
GO
CHECKPOINT;
DBCC DROPCLEANBUFFERS;
GO

--run this on session 1 after changing time to a near future value
WAITFOR TIME '12:00:00';
UPDATE dbo.Example SET Col3 = 1 WHERE Col2 = 1;
GO

--run this on session 2 after changing time to same time as session 1
WAITFOR TIME '12:00:00';
UPDATE dbo.Example SET Col2 = 2 WHERE Col3 = 1;
GO

我在这个脚本中使用了大量的行,因为即使在快速的机器上也能可靠地再现死锁。请记住,死锁是一个时间问题所以我希望可以在慢速框上使用更少的行来重现死锁。

即使使用小表,高效查询和自动单语句事务,当查询通过不同的访问路径访问同一资源时,也可能发生死锁(尽管不太可能)。此示例中的查询使用不同的索引,因此不同的锁定顺序可能导致死锁。