为什么这些sql语句会死锁?(包括图表)

时间:2016-03-02 13:15:06

标签: sql entity-framework database-deadlocks

我很惊讶地看到一个非常基本的更新声明& select语句可能会变成死锁 我的印象是,如果2个进程在无穷远处等待,那么你只能陷入僵局。我没有得到的是为什么这两个过程不能只是等待彼此。任何帮助将不胜感激。

1个查询来自实体框架,运行非常激烈(大约每2秒一次)。

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] &gt; @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] &gt; @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] &gt; @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>

修改的 表上有一些触发器,简而言之就是更新触发器: NUMBER1:

IF EXISTS (SELECT EventID FROM deleted WHERE SubscriptionID = 7379958 and PersonID > 0) 
AND EXISTS (SELECT EventID FROM INSERTED WHERE SubscriptionID = 7379958 and PersonID = 0) 
BEGIN
    RAISERROR('Can''t reset to PersonID 0',16,1)
    ROLLBACK

END

2号:

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

0 个答案:

没有答案