2010-06-24 7 views
5

Tengo dos procedimientos almacenados ejecutándose en subprocesos separados, ejecutándose en SQL Server 2005. Un procedimiento inserta filas nuevas en un conjunto de tablas y el otro procedimiento elimina datos antiguos del mismo conjunto de tablas. Estos procedimientos se están ejecutando en un punto muerto en las tablas DLevel y Modelo. Aquí está el esquema:¿Cómo puedo evitar un punto muerto entre estas dos declaraciones SQL?

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

Tabla DFile: Clave principal = DFileID
Tabla dlevel: clave principal = DLevelID, Exteriores Clave: DFileID
Tabla Modelo: Clave principal = ID de modelo, clave externa: DFileID
Tabla Elemento: Clave principal = ElementID, Clave externa1: DFileID, Extranjero Clave2: DLevelID

He aislado las dos sentencias SQL exactas (una de cada procedimiento almacenado) que están causando el interbloqueo. He visto el punto muerto informado por cualquiera de los procedimientos. Uso top (1000) en ambos casos y ambas sentencias se ejecutan en un bucle hasta que se completen sin dejar filas para eliminar/insertar.

SQL Declaración 1:

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

instrucción SQL 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: Los valores de @ fileID1 y @ fileID2 siempre se garantiza que sea diferente . La tabla de nivel tiene un promedio de aprox. 60 filas para un solo DFileID y así completaría la eliminación de todas las filas en una sola pasada.

¿Cómo puedo evitar un punto muerto entre estas dos declaraciones SQL?

Editar 1: Reescrito para aclarar mejor el problema; imagen agregada; SQL simplificado y eliminado join a la tabla DLevel, que no contribuyó al punto muerto.

Editar 2: Se agregó XML del gráfico de interbloqueo.
El bloqueo se produce ahora en Tabla de modelo. Esquema y declaración de eliminación similares para Modelo como para Tabla de 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

¿qué versión de SQL server? ¡¡Apuesto a que es en SQL 2000 !! –

+0

¿Existen restricciones de clave externa entre DLevel y Element? –

+0

Enlace roto: la versión es SQL Server 2005 Express. – Elan

Respuesta

0

Sospecho que debe haber algún tipo de violación de clave con eliminar e insertar al mismo tiempo ..?

1

Un posible escenario: una conexión inserta una fila en Element, y esa fila se refiere a una fila en DLevel, y esa fila en DLevel está siendo eliminada por otra conexión. Su sugerencia de nolock no se aplica a claves externas.

+0

Estas declaraciones se ejecutan en conexiones separadas. Las filas (de la tabla DLevel) a las que hacen referencia las instrucciones de inserción y eliminación son siempre diferentes ya que DFileID es diferente entre las dos. Si el nolock no se aplica a las claves externas, entonces tal vez las dos declaraciones se estén ejecutando en conflictos de bloqueo de página. Soy consciente de desactivar el bloqueo de filas y páginas, pero ¿hay alguna forma de forzar el bloqueo del nivel de la fila? – Elan

+0

Eliminado unirse a la tabla DLevel en la consulta "insertar en elemento ...". Todavía consigue el punto muerto. – Elan

1

Puede intentar eliminar la clave externa a DLevel.DFileID de la tabla de elementos. Como tiene una clave principal en DLevel.DlevelID y la referencia como una clave externa en Element, la clave externa DFileID no es realmente necesaria.

Cuestiones relacionadas