Estaba insertando dos conjuntos de datos, utilizando un registro mínimo, en una tabla de montón vacía mediante dos tareas Ejecutar SQL que se ejecutan en paralelo y con SQL de la siguiente forma.
INSERT INTO Table (TABLOCK) SELECT FROM ...
Después de que el trabajo se bloquea un poco, una de las tareas de SQL se convirtió en una víctima de punto muerto. A continuación se muestra la salida XML del gráfico de punto muerto.
¿Alguien puede explicar lo que estaba sucediendo debajo del capó?
<resource-list>
<objectlock lockPartition="0" objid="1586156746" subresource="FULL" dbid="7" objectname="dbo.TargetTable" id="lock7374a00" mode="IX" associatedObjectId="1586156746">
<owner-list>
<owner id="process9609dc8" mode="Sch-S"/>
<owner id="process9609dc8" mode="IX"/>
</owner-list>
<waiter-list>
<waiter id="process5e13048" mode="X" requestType="convert"/>
</waiter-list>
</objectlock>
<objectlock lockPartition="0" objid="1586156746" subresource="FULL" dbid="7" objectname="dbo.TargetTable" id="lock7374a00" mode="IX" associatedObjectId="1586156746">
<owner-list>
<owner id="process5e13048" mode="Sch-S"/>
<owner id="process5e13048" mode="IX"/>
</owner-list>
<waiter-list>
<waiter id="process9609dc8" mode="X" requestType="convert"/>
</waiter-list>
</objectlock>
</resource-list>
Las cosas se ponen mucho más complicadas porque descubrí que, en la mayoría de los casos, las dos tareas Ejecutar SQL pueden ejecutarse en paralelo con éxito. Prueba a continuación:
Create table dbo.TablockInsert (c1 int, c2 int, c3 int)
--then issue the script in two Execute Sql Task in parallel you won't fail:
insert into dbo.TablockInsert(TABLOCK) SELECT 1, 1, 1
Dado que la única diferencia es la instrucción SELECT ... FROM ..., ¿parece que la instrucción SELECT ... FROM ... puede tener un impacto en el modo de bloqueo aquí?
Respuestas:
La Guía de rendimiento de carga de datos se escribió para SQL Server 2008, pero por lo que puedo decir, Microsoft no ha realizado ninguna mejora en esta área para los montones. Aquí hay una cotización para su escenario de carga:
La parte importante es que no obtienes un bloqueo BU con
INSERT ... SELECT
. Siempre obtendrá un bloqueo exclusivo en la mesa, por lo que solo unoINSERT
puede correr a la vez.En los comentarios, dijo que insertará 100k filas o menos y que otros procesos no se ejecutarán en las tablas durante las inserciones. Al enviar dos consultas INSERT a la base de datos, esperaría que suceda una de estas tres cosas:
En todos los casos, usted se beneficia o no se ve perjudicado al agregar una
TABLOCKX
pista a la consulta, por lo que esa es mi recomendación de evitar el punto muerto. Si quieres saber por qué a veces ocurre el punto muerto, tendrás que buscar otra respuesta para eso.En un escenario diferente en el que realmente necesita una inserción paralela, dos formas de solucionar el problema de la BU son particionar su montón y hacer que cada sesión se inserte en una partición separada o cargar sus datos a través de BCP, BULK INSERT o Integration Services .
fuente
Se está insertando
dbo.TargetTable
desde dos sesiones y ambas utilizando unaTABLOCK
sugerencia. Tanto la retenciónprocess9609dc8
como elprocess5e13048
procesoSch-S
y losIX
bloqueos que son compatibles entre sí para que ambos procesos puedan mantenerse al mismo tiempo. Pero ambos quieren convertir elIX
bloqueo alExclusive X
tipo.X
Las cerraduras no son compatibles entre sí. Por lo tanto, el servidor SQL eligió una de las sesiones como víctima de punto muerto en lugar de esperar infinitamente el uno al otro.Información básica de bloqueo.
Gráfico de compatibilidad de bloqueos (motor de base de datos).
Detección y finalización de puntos muertos.
fuente