外键会导致死锁并阻碍“读取已提交的快照”吗?


19

这是来自以下方面的后续问题:https : //stackoverflow.com/questions/7684477/is-it-possible-to-set-transaction-isolation-level-snapshot-automatically

尽管同时运行大型报表时,我仍然在ASP.NET应用程序中遇到死锁/超时的情况READ_COMMITTED_SNAPSHOT ON

所以我有两个问题:

  1. 如何检查“ 事务隔离级别快照”是否按预期运行/完全正常?
  2. 我假设外键(在Web应用程序表中的报表表中)引起死锁。我发现这篇有趣的文章

注意 SQL Server在验证外键时会获取共享锁,即使该事务使用的是读取提交的快照(使用行版本控制读取的提交)或快照隔离级别。当使用这些事务隔离级别检查来自事务的死锁图时,请注意这一点。如果看到共享锁,请检查是否对由外键引用的对象进行了锁定。

如何检查FK是否真正引起了死锁/超时情况,这是否意味着我可以删除那些外键以防止死锁(这是可以接受的工作)?

注意:我只是从导致死锁的表中读取。

对此主题的任何想法都将不胜感激。


编辑 这是一个死锁图。也许有人可以帮助我了解造成僵局的原因。似乎是在没有任何报告仅由Web应用程序运行的情况下发生的,当两个事务要写入同一个表时(一个更新和一个插入,该插入与存储过程相同)。为什么要获取页锁?如何仅启用行锁?Insert-SP已使用TRANSACTION ISOLATION LEVEL REPEATABLE READ

我非常怀疑两个触发器(一个更新和一个插入)是造成死锁的原因。这是插入触发器:

CREATE TRIGGER [dbo].[CreateRMAFiDates] 
   ON  [dbo].[RMA] 
   AFTER INSERT
AS 
BEGIN
    SET NOCOUNT ON;

    UPDATE RMA 
    SET [fiCreationDate]=(SELECT idDate FROM tdefDate 
        WHERE CONVERT(VARCHAR, INSERTED.Creation_Date, 112) = tdefDate.Text),
        [fiPopDate]=(SELECT idDate FROM tdefDate 
        WHERE CONVERT(VARCHAR, INSERTED.POP_Date, 112) = tdefDate.Text),
        [fiManufactureDate]=(SELECT idDate FROM tdefDate 
        WHERE CONVERT(VARCHAR, INSERTED.Manufacture_Date, 112) = tdefDate.Text)
    FROM INSERTED;
END

因此,此触发器会更新RMA表,从而导致触发更新触发器(作用类似)。僵局图是否证实了我的假设?我认为我将删除这些触发器并创建一个每天运行一次的SP,这将完全足够,因为这些列仅用于SSAS-Cube(Molap)。

编辑:顺便说一句,因为我删除了这些触发器,所以不再有死锁:)

Answers:


16

如果SQLCAT团队说FK 验证是使用读提交隔离来完成的,那么他们必须知道他们在说什么。强调验证。真正的问题是,为什么报告会触发FK验证?验证发生在写入时,并且报告应该被读取。您的报告正在引起写入,在这种情况下,快照隔离级别将无济于事,无论是死锁的原因是不同的。

取得进展的唯一方法是捕获死锁图。

至于另一个问题,如何检查是否在快照隔离下运行:请参阅sys.dm_tran_active_snapshot_database_transactions


2

外键验证 下(锁定)发生读取已提交的正确性。请参阅快照隔离:对完整性的威胁?详情请见Hugo Kornelis。

死锁图显示了两个并发执行 RM2.dbo.RMA导致死锁的。您的触发器缺少RMA和之间的联接条件inserted

似乎这是一个疏忽,您的触发器意外地更新了其中的所有行,RMA因此如果执行多个并发触发器,则极有可能发生死锁。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.