为什么这些sql语句会死锁?(包括图表)
我很惊讶地看到,一个非常基本的update语句&select语句会变成死锁。 我的印象是,只有当两个进程相互等待无限长时间时,才会出现死锁。我不明白为什么这两个进程不能互相等待。任何帮助都将不胜感激 1查询来自实体框架,大约每2秒运行一次为什么这些sql语句会死锁?(包括图表),sql,entity-framework,database-deadlocks,Sql,Entity Framework,Database Deadlocks,我很惊讶地看到,一个非常基本的update语句&select语句会变成死锁。 我的印象是,只有当两个进程相互等待无限长时间时,才会出现死锁。我不明白为什么这两个进程不能互相等待。任何帮助都将不胜感激 1查询来自实体框架,大约每2秒运行一次 SELECT [Extent1].[SubscriptionID] AS [SubscriptionID], [Extent1].[ClientID] AS [ClientID], [Extent1].[SubClientID] AS [SubClien
SELECT
[Extent1].[SubscriptionID] AS [SubscriptionID],
[Extent1].[ClientID] AS [ClientID],
[Extent1].[SubClientID] AS [SubClientID],
[Extent1].[CAClientID] AS [CAClientID],
CASE WHEN ([Extent1].[ArrivalTime] IS NULL) THEN @p__linq__1 ELSE [Extent1].[ArrivalTime] END AS [C1],
[Extent1].[UpdateDate] AS [UpdateDate]
FROM [dbo].[CA_Event_Person] AS [Extent1]
WHERE ([Extent1].[UpdateDate] IS NOT NULL) AND ([Extent1].[UpdateDate] > @p__linq__0)
另一个正在进行更新:
UPDATE
CA_Event_Person
SET
UpdatePersonID = @PersonID,
UpdateDate = GETDATE(),
AutoAssign = ISNULL(@AutoAssign, AutoAssign)
WHERE SubscriptionID = @SubscriptionID
完全死锁图:
<deadlock-list>
<deadlock victim="processc35888508">
<process-list>
<process id="processc35888508" taskpriority="0" logused="0" waitresource="KEY: 9:72057707739217920 (fa9c88953e05)" waittime="3892" ownerId="39577235946" transactionname="SELECT" lasttranstarted="2016-03-02T13:36:42.027" XDES="0x80099800" lockMode="S" schedulerid="15" kpid="9996" status="suspended" spid="109" sbid="0" ecid="5" priority="0" trancount="0" lastbatchstarted="2016-03-02T13:36:42.027" lastbatchcompleted="2016-03-02T13:36:42.027" clientapp="iXtranet.NET2" hostname="HB2949" hostpid="4244" isolationlevel="read committed (2)" xactid="39577235946" currentdb="9" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
<executionStack>
<frame procname="adhoc" line="1" stmtstart="102" sqlhandle="0x02000000263a730faf73af4e669327dd034762624d86b5aa">
SELECT
[Extent1].[SubscriptionID] AS [SubscriptionID],
[Extent1].[ClientID] AS [ClientID],
[Extent1].[SubClientID] AS [SubClientID],
[Extent1].[CAClientID] AS [CAClientID],
CASE WHEN ([Extent1].[ArrivalTime] IS NULL) THEN @p__linq__1 ELSE [Extent1].[ArrivalTime] END AS [C1],
[Extent1].[UpdateDate] AS [UpdateDate]
FROM [dbo].[CA_Event_Person] AS [Extent1]
WHERE ([Extent1].[UpdateDate] IS NOT NULL) AND ([Extent1].[UpdateDate] > @p__linq__0) </frame>
<frame procname="unknown" line="1" sqlhandle="0x000000000000000000000000000000000000000000000000">
unknown </frame>
</executionStack>
<inputbuf>
</inputbuf>
</process>
<process id="processf1137fdc8" taskpriority="0" logused="296" waitresource="PAGE: 9:1:11298302" waittime="4074" ownerId="39577243359" transactionname="UPDATE" lasttranstarted="2016-03-02T13:36:42.217" XDES="0x1c47b7280" lockMode="IX" schedulerid="12" kpid="10040" status="suspended" spid="237" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2016-03-02T13:36:42.217" lastbatchcompleted="2016-03-02T13:36:42.213" clientapp="Internet Information Services" hostname="HB2949" hostpid="4244" loginname="WEBCLASSIC2" isolationlevel="read committed (2)" xactid="39577243359" currentdb="9" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
<executionStack>
<frame procname="dixyscom.dbo.CA_stp_Subscription_Resource_Append" line="131" stmtstart="7222" sqlhandle="0x03000900ab5fd53ec3e5e3005aa500000100000000000000">
UPDATE
CA_Event_Person
SET
UpdatePersonID = @PersonID,
UpdateDate = GETDATE(),
AutoAssign = ISNULL(@AutoAssign, AutoAssign)
WHERE
SubscriptionID = @SubscriptionID </frame>
</executionStack>
<inputbuf>
Proc [Database Id = 9 Object Id = 1054171051] </inputbuf>
</process>
<process id="process10ad13e748" taskpriority="0" logused="10000" waittime="3892" schedulerid="22" kpid="5452" status="suspended" spid="109" sbid="0" ecid="0" priority="0" trancount="0" lastbatchstarted="2016-03-02T13:36:42.027" lastbatchcompleted="2016-03-02T13:36:42.027" clientapp="iXtranet.NET2" hostname="HB2949" hostpid="4244" loginname="WEBDOTNET3" isolationlevel="read committed (2)" xactid="39577235946" currentdb="9" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
<executionStack>
<frame procname="adhoc" line="1" stmtstart="102" sqlhandle="0x02000000263a730faf73af4e669327dd034762624d86b5aa">
SELECT
[Extent1].[SubscriptionID] AS [SubscriptionID],
[Extent1].[ClientID] AS [ClientID],
[Extent1].[SubClientID] AS [SubClientID],
[Extent1].[CAClientID] AS [CAClientID],
CASE WHEN ([Extent1].[ArrivalTime] IS NULL) THEN @p__linq__1 ELSE [Extent1].[ArrivalTime] END AS [C1],
[Extent1].[UpdateDate] AS [UpdateDate]
FROM [dbo].[CA_Event_Person] AS [Extent1]
WHERE ([Extent1].[UpdateDate] IS NOT NULL) AND ([Extent1].[UpdateDate] > @p__linq__0) </frame>
<frame procname="unknown" line="1" sqlhandle="0x000000000000000000000000000000000000000000000000">
unknown </frame>
</executionStack>
<inputbuf>
(@p__linq__0 datetime2(7),@p__linq__1 datetime2(7))SELECT
[Extent1].[SubscriptionID] AS [SubscriptionID],
[Extent1].[ClientID] AS [ClientID],
[Extent1].[SubClientID] AS [SubClientID],
[Extent1].[CAClientID] AS [CAClientID],
CASE WHEN ([Extent1].[ArrivalTime] IS NULL) THEN @p__linq__1 ELSE [Extent1].[ArrivalTime] END AS [C1],
[Extent1].[UpdateDate] AS [UpdateDate]
FROM [dbo].[CA_Event_Person] AS [Extent1]
WHERE ([Extent1].[UpdateDate] IS NOT NULL) AND ([Extent1].[UpdateDate] > @p__linq__0) </inputbuf>
</process>
</process-list>
<resource-list>
<keylock hobtid="72057707739217920" dbid="9" objectname="dixyscom.dbo.CA_Event_Person" indexname="CIX_CA_Event_Person" id="lock2dda41680" mode="X" associatedObjectId="72057707739217920">
<owner-list>
<owner id="processf1137fdc8" mode="X"/>
</owner-list>
<waiter-list>
<waiter id="processc35888508" mode="S" requestType="wait"/>
</waiter-list>
</keylock>
<pagelock fileid="1" pageid="11298302" dbid="9" objectname="dixyscom.dbo.CA_Event_Person" id="lock44facf180" mode="S" associatedObjectId="72057707632197632">
<owner-list>
<owner id="process10ad13e748" mode="S"/>
</owner-list>
<waiter-list>
<waiter id="processf1137fdc8" mode="IX" requestType="wait"/>
</waiter-list>
</pagelock>
<exchangeEvent id="Pipecd899e380" WaitType="e_waitPipeGetRow" nodeId="1">
<owner-list>
<owner id="processc35888508"/>
</owner-list>
<waiter-list>
<waiter id="process10ad13e748"/>
</waiter-list>
</exchangeEvent>
</resource-list>
</deadlock>
</deadlock-list>
第二点:
IF EXISTS (SELECT EventID FROM DELETED WHERE EventID > 0) OR EXISTS (SELECT EventID FROM INSERTED WHERE EventID > 0) BEGIN ...
[Enter 30 lines of code that i'm assuming are being skipped due to the no insert or delete)
第3个是更新后触发器:
ALTER TRIGGER [dbo].[trig_CA_Event_Person_RN_Availability_Recalculate_OnUpdate]
ON [dbo].[CA_Event_Person]
AFTER UPDATE
AS
IF Update(EventID) OR Update(NOPersons) OR Update(StatusID) OR Update(Deleted) OR Update(Cancelled) OR Update(WaitinglistPosition) OR Update(CanBeOverTaken) BEGIN
INSERT INTO
RN_Availability_Recalculate
(
ClientID,
SubClientID,
ApplicationID,
CA_CAClientID,
CA_EventID,
InsertPersonID,
InsertDate,
CompanyID,
Reference
)
SELECT
CA_Event_Head.ClientID,
CA_Event_Head.SubClientID,
CA_Event_Head.ApplicationID,
CA_Event_Head.CAClientID,
CA_Event_Head.EventID,
INSERTED.InsertPersonID,
GETDATE(),
Company.CompanyID,
'trig_CA_Event_Person_RN_OnUpdate'
FROM
INSERTED
INNER JOIN deleted
ON deleted.SubscriptionID = INSERTED.SubscriptionID
AND (
deleted.EventID <> INSERTED.EventID
OR deleted.NOPersons <> INSERTED.NOPersons
OR deleted.ArrivalTime <> INSERTED.ArrivalTime
OR (
deleted.StatusID <> INSERTED.StatusID
AND INSERTED.StatusID IN (50, 98, 99) --vertrokken of geannuleerd
)
)
INNER JOIN CA_Event_Head WITH(NOLOCK)
ON INSERTED.EventID = CA_Event_Head.EventID
INNER JOIN Company WITH(NOLOCK)
ON CA_Event_Head.ClientID = Company.REF_ClientID
AND CA_Event_Head.CAClientID = Company.REF_CA_CAClientID
AND CA_Event_Head.ApplicationID = Company.REF_ApplicationID
WHERE
INSERTED.EventID > 0
AND INSERTED.EventID NOT IN (SELECT CA_EventID FROM RN_Availability_Recalculate WITH (NOLOCK))
AND CA_Event_Head.CAClientID > 0
AND CA_Event_Head.PublicSubscription = 1
AND CA_Event_Head.BlockPublicSubscription = 0
AND CA_Event_Head.EndTime >= GETDATE()
END
至于为什么我不确定,但是您是否尝试过从IsolationLevel=ReadUncommitted的事务运行EF查询?这可能会给你一个解决方法,或者帮助你调试。你的表上有触发器吗?您是否从应用程序中启动任何事务?到目前为止,我只看到热生产环境中的死锁。我怀疑只是在不知道发生了什么的情况下尝试一些东西。两个查询都在同一个事务中运行?select查询在transaction?@TomH下。应用程序中没有启动任何事务。我刚检查过,似乎有太多。。。叹气。很明显,触发器是坏的,但是它们可能会导致死锁吗?至于为什么我不确定,但是您是否尝试过从IsolationLevel=ReadUncommitted的事务运行EF查询?这可能会给你一个解决方法,或者帮助你调试。你的表上有触发器吗?您是否从应用程序中启动任何事务?到目前为止,我只看到热生产环境中的死锁。我怀疑只是在不知道发生了什么的情况下尝试一些东西。两个查询都在同一个事务中运行?select查询在transaction?@TomH下。应用程序中没有启动任何事务。我刚检查过,似乎有太多。。。叹气。显然,触发器是不好的,但它们是否可能与死锁有关?
ALTER TRIGGER [dbo].[trig_CA_Event_Person_RN_Availability_Recalculate_OnUpdate]
ON [dbo].[CA_Event_Person]
AFTER UPDATE
AS
IF Update(EventID) OR Update(NOPersons) OR Update(StatusID) OR Update(Deleted) OR Update(Cancelled) OR Update(WaitinglistPosition) OR Update(CanBeOverTaken) BEGIN
INSERT INTO
RN_Availability_Recalculate
(
ClientID,
SubClientID,
ApplicationID,
CA_CAClientID,
CA_EventID,
InsertPersonID,
InsertDate,
CompanyID,
Reference
)
SELECT
CA_Event_Head.ClientID,
CA_Event_Head.SubClientID,
CA_Event_Head.ApplicationID,
CA_Event_Head.CAClientID,
CA_Event_Head.EventID,
INSERTED.InsertPersonID,
GETDATE(),
Company.CompanyID,
'trig_CA_Event_Person_RN_OnUpdate'
FROM
INSERTED
INNER JOIN deleted
ON deleted.SubscriptionID = INSERTED.SubscriptionID
AND (
deleted.EventID <> INSERTED.EventID
OR deleted.NOPersons <> INSERTED.NOPersons
OR deleted.ArrivalTime <> INSERTED.ArrivalTime
OR (
deleted.StatusID <> INSERTED.StatusID
AND INSERTED.StatusID IN (50, 98, 99) --vertrokken of geannuleerd
)
)
INNER JOIN CA_Event_Head WITH(NOLOCK)
ON INSERTED.EventID = CA_Event_Head.EventID
INNER JOIN Company WITH(NOLOCK)
ON CA_Event_Head.ClientID = Company.REF_ClientID
AND CA_Event_Head.CAClientID = Company.REF_CA_CAClientID
AND CA_Event_Head.ApplicationID = Company.REF_ApplicationID
WHERE
INSERTED.EventID > 0
AND INSERTED.EventID NOT IN (SELECT CA_EventID FROM RN_Availability_Recalculate WITH (NOLOCK))
AND CA_Event_Head.CAClientID > 0
AND CA_Event_Head.PublicSubscription = 1
AND CA_Event_Head.BlockPublicSubscription = 0
AND CA_Event_Head.EndTime >= GETDATE()
END