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>
¿qué versión de SQL server? ¡¡Apuesto a que es en SQL 2000 !! –
¿Existen restricciones de clave externa entre DLevel y Element? –
Enlace roto: la versión es SQL Server 2005 Express. – Elan