2010-06-24 13 views
5

Ho due stored procedure in esecuzione in thread separati, in esecuzione su SQL Server 2005. Una procedura inserisce nuove righe in un set di tabelle e l'altra procedura elimina i vecchi dati dallo stesso set di tabelle. Queste procedure si stanno verificando in un deadlock sui tavoli DLevel e Modello. Ecco lo schema:Come posso evitare un deadlock tra queste due istruzioni SQL?

Scrollbar Image http://www.barramsoft.com/pub/images/DeadLock2.jpg

Tabella dfile: Chiave primaria = DFileID
Tabella dlevel: Chiave primaria = DLevelID, degli Esteri chiave: DFileID
Tabella Modello: Chiave primaria = ID modello, chiave esterna: DFileID
Tabella Elemento: Chiave primaria = ElementID, Chiave esterna1: DFileID, Esterna Key2: DLevelID

Ho isolato le due istruzioni SQL esatte (una per ogni stored procedure) che causano il deadlock. Ho visto lo stallo segnalato da una delle procedure. Io uso top (1000) in entrambi i casi e entrambe le istruzioni sono eseguite in un ciclo finché non si completano senza righe da eliminare/inserire.

SQL Statement 1:

while (...) 
begin 
    delete top (1000) from DLevel where DFileID = @fileID1 
    ... 
end 

SQL Statement 2:

while (...) 
begin 
    insert into Element (ElementID, DFileID, LevelNum, ...) 
     select top (1000) el.ElementID, el.DFileID, el.LevelNum, ... 
     from ElementLoader el with (nolock) 
       left outer join Element e with (nolock) 
        on e.ElementID = el.ElementID 
     where el.DFileID = @fileID2 
     and e.ElementID is null 
     order by el.ElementID 
    ... 
end 

Nota: I valori per @ fileID1 e @ fileID2 è sempre garantita essere diverso . Il tavolo DLevel ha in media ca. 60 righe per un singolo DFileID e quindi completare l'eliminazione di tutte le righe in un unico passaggio.

Come evitare un deadlock tra queste due istruzioni SQL?

Modifica 1: Riscritto per chiarire meglio il problema; immagine aggiunta; SQL semplificato e rimosso si uniscono alla tabella DLevel, che non ha contribuito al deadlock.

Modifica 2: Aggiunto XML del grafico di deadlock.
Il deadlock ora si verifica nella tabella Modello. Istruzione e schema di cancellazione simili per Modello come per la tabella DLevel.

<deadlock victim="process2bae38"> 
    <process-list> 
     <process id="process2bae38" taskpriority="0" logused="4760" waitresource="PAGE: 11:1:1946" waittime="46" ownerId="4127445" transactionname="DELETE" lasttranstarted="2010-06-24T16:19:00.107" XDES="0xffffffff90552ae0" lockMode="S" schedulerid="1" kpid="14252" status="suspended" spid="58" sbid="0" ecid="0" priority="0" transcount="2" lastbatchstarted="2010-06-24T16:19:00.107" lastbatchcompleted="2010-06-24T16:19:00.107" clientapp=".Net SqlClient Data Provider" hostname="LT0103" hostpid="1668" loginname="NT AUTHORITY\SYSTEM" isolationlevel="read committed (2)" xactid="4127445" currentdb="11" lockTimeout="4294967295" clientoption1="673185824" clientoption2="128056"> 
      <executionStack> 
       <frame procname="CadExplorer5.dbo.pCleanUpOldFiles" line="364" stmtstart="23718" stmtend="23834" sqlhandle="0x03000b00fb1c2229b1a7f7009f9d00000100000000000000"> 
delete top (@batchSize) from Model where DFileID = @fileID  </frame> 
      </executionStack> 
      <inputbuf> 
Proc [Database Id = 11 Object Id = 690101499] </inputbuf> 
     </process> 
     <process id="process2c95b8" taskpriority="0" logused="283388" waitresource="KEY: 11:72057594039304192 (8100bdf15e8b)" waittime="78" ownerId="4127412" transactionname="INSERT" lasttranstarted="2010-06-24T16:19:00.103" XDES="0xffffffff81d5ef18" lockMode="S" schedulerid="2" kpid="8460" status="suspended" spid="63" sbid="0" ecid="0" priority="0" transcount="2" lastbatchstarted="2010-06-24T16:18:59.413" lastbatchcompleted="2010-06-24T16:18:59.413" clientapp=".Net SqlClient Data Provider" hostname="LT0103" hostpid="1668" loginname="NT AUTHORITY\SYSTEM" isolationlevel="read committed (2)" xactid="4127412" currentdb="11" lockTimeout="4294967295" clientoption1="673185824" clientoption2="128056"> 
      <executionStack> 
       <frame procname="CadExplorer5.dbo.pLoadElements" line="288" stmtstart="28796" stmtend="33194" sqlhandle="0x03000b00a689fe2b2c5107019f9d00000100000000000000"> 
insert into Element (
         ElementID, DFileID, ModelID, ElementTypeID, CADElementID, 
         ParentID, 
         LevelNum, 
         Depth, NumChildren, 
         Color, Weight, Style, Xlo, Ylo, Zlo, Xhi, Yhi, Zhi, 
         Diagonal, XCenter, 
         BitFlags, ElementModTime 
         ) 
        select top (@batchSize) 
         el.ElementID, el.DFileID, el.ModelID, el.ElementTypeID, el.CADElementID, 
         parent.ElementID as ParentID, 
         (case when el.LoaderType = 1 and et.IsGraphical = 1 then el.LevelAttrib else null end) as LevelNum, 
         --l.LevelNum, 
         el.Depth, el.NumChildren, 
         el.Color, el.Weight, el.Style, el.Xlo, el.Ylo, el.Zlo, el.Xhi, el.Yhi, el.Zhi, 
         el.Diagonal, el.XCenter,  </frame> 
      </executionStack> 
      <inputbuf> 
Proc [Database Id = 11 Object Id = 738101670] </inputbuf> 
     </process> 
    </process-list> 
    <resource-list> 
     <pagelock fileid="1" pageid="1946" dbid="11" objectname="CadExplorer5.dbo.Element" id="lockffffffff86ffd080" mode="IX" associatedObjectId="72057594039107584"> 
      <owner-list> 
       <owner id="process2c95b8" mode="IX"/> 
      </owner-list> 
      <waiter-list> 
       <waiter id="process2bae38" mode="S" requestType="wait"/> 
      </waiter-list> 
     </pagelock> 
     <keylock hobtid="72057594039304192" dbid="11" objectname="CadExplorer5.dbo.Model" indexname="PK_Model" id="lockffffffff8d66db80" mode="X" associatedObjectId="72057594039304192"> 
      <owner-list> 
       <owner id="process2bae38" mode="X"/> 
      </owner-list> 
      <waiter-list> 
       <waiter id="process2c95b8" mode="S" requestType="wait"/> 
      </waiter-list> 
     </keylock> 
    </resource-list> 
</deadlock> 
+0

quale versione del server SQL? Scommetto che questo è in SQL 2000 !! –

+0

Esistono vincoli di chiave esterna tra DLevel ed Element? –

+0

Collegamento interrotto: la versione è SQL Server 2005 Express. – Elan

risposta

0

Sospetto che ci sia qualche tipo di violazione della chiave con cancellazione e inserimento in corso contemporaneamente ..?

1

Uno scenario possibile: una connessione inserisce una riga in Elemento e quella riga fa riferimento a una riga in DLevel e quella riga in DLevel viene eliminata da un'altra connessione. Il tuo suggerimento nolock non si applica alle chiavi esterne.

+0

Queste istruzioni sono eseguite in connessioni separate. Le righe (della tabella DLevel) a cui fanno riferimento le istruzioni insert e delete sono sempre diverse in quanto DFileID è diverso tra i due. Se il nolock non si applica alle chiavi esterne, allora forse le due istruzioni sono in esecuzione in conflitti di blocco della pagina. Sono consapevole di disattivare il blocco di righe e pagine, ma esiste un modo per forzare il blocco a livello di riga? – Elan

+0

Rimosso join alla tabella DLevel nella query "insert into Element ...". Ancora ottenere lo stallo. – Elan

1

Si potrebbe provare a rimuovere la chiave esterna da DLevel.DFileID dalla tabella degli elementi. Poiché hai una chiave primaria su DLevel.DlevelID e la fai riferimento come chiave esterna in Element, la chiave esterna DFileID non è realmente necessaria.

Problemi correlati