SELECCIONAR / INSERTAR un punto muerto

10

Esta instancia aloja las bases de datos de SharePoint 2007 (SP). Hemos estado experimentando numerosos puntos muertos SELECT / INSERT contra una tabla muy utilizada dentro de la base de datos de contenido SP. He reducido los recursos involucrados, ambos procesos requieren bloqueos en el índice no agrupado.
INSERT necesita un bloqueo IX en el recurso SELECT y SELECT necesita un bloqueo S en el recurso INSERT. El gráfico de punto muerto muestra tres recursos, 1.) dos de SELECT (subprocesos paralelos de productor / consumidor) y 2.) INSERT.
He adjuntado el gráfico de punto muerto para su revisión. Como se trata de estructuras de tablas y códigos de Microsoft, no podemos realizar ningún cambio.
Sin embargo, he leído, en el sitio de MSFT SP, que recomiendan establecer la opción de configuración de nivel de instancia MAXDOP en 1. Dado que esta instancia se comparte entre muchas otras bases de datos / aplicaciones, esta configuración no se puede deshabilitar.


Por lo tanto, decidí intentar evitar que estas instrucciones SELECT fueran paralelas. Sé que esto no es una solución, sino más bien una modificación temporal para ayudar con la resolución de problemas. Por lo tanto, aumenté el "Umbral de costo para paralelismo" de nuestro estándar de 25 a 40 al hacerlo, a pesar de que la carga de trabajo no ha cambiado (SELECCIONAR / INSERTAR con frecuencia) los puntos muertos han desaparecido. Mi pregunta es por qué

SPID 356 INSERT tiene un bloqueo IX en una página que pertenece al índice no agrupado
SPID 690 SELECCIONAR ID de ejecución 0 tiene bloqueo S en una página que pertenece al mismo índice no agrupado

Ahora

SPID 356 quiere un bloqueo IX en el recurso SPID 690 pero no puede mantenerlo porque SPID 356 está siendo bloqueado por SPID 690 ID de ejecución 0 Bloqueo S
SPID 690 ID de ejecución 1 quiere un bloqueo S en el recurso SPID 356 pero no puede obtenerlo porque SPID 690 ID de ejecución 1 está siendo bloqueado por SPID 356 y ahora tenemos nuestro punto muerto.

El plan de ejecución se puede encontrar en mi SkyDrive

Los detalles completos del punto muerto se pueden encontrar aquí

Si alguien me puede ayudar a entender por qué realmente lo agradecería.

Tabla de EventReceivers.
Id. Identificador único no 16
Nombre nvarchar no 512
Id. Del sitio identificador único no 16
WebId identificador único no 16
HostId identificador único no 16
HostType int no 4
ItemId int no 4
DirName nvarchar no 512
LeafName nvarchar no 256
Tipo int no 4
SequenceNumber int no 4
Ensamblaje nvarchar no 512
Clase nvarchar no 512
Datos nvarchar no 512
Filtro nvarchar no 512
SourceId tContentTypeId no 512
SourceType int no 4
Credential int no 4
ContextType varbinary no 16
ContextEventType varbinary no 16
ContextId varbinary no 16
ContextObjectId varbinary no 16
ContextCollectionId varbinary no 16

index_name index_description index_keys
EventReceivers_ByContextCollectionId no agrupado situado en PRIMARIO SiteID, ContextCollectionId
EventReceivers_ByContextObjectId no agrupados encuentra en PRIMARIO SiteID, ContextObjectId
EventReceivers_ById no agrupados, único situado en PRIMARIO SiteID, Id
EventReceivers_ByTarget agrupado, exclusivo situado en PRIMARIO SiteID, WebID, hostid, HOSTTYPE, Tipo, ContextCollectionId, ContextObjectId, ContextId, ContextType, ContextEventType, SequenceNumber, Assembly, Class
EventReceivers_IdUnique clave no agrupada, única, única ubicada en PRIMARY Id

SQLJarHead
fuente
2
¿Qué hacemos proc_InsertEventReceivery proc_InsertContextEventReceiverhacemos que no podemos ver en el XDL? También para reducir el paralelismo, ¿por qué no solo afectar estas declaraciones directamente (usando MAXDOP 1) en lugar de anular con configuraciones de todo el servidor?
Aaron Bertrand
1
Tengo curiosidad por saber cuál es su configuración MAXDOP de servidor y cuántos procesadores (lógico) tiene. SharePoint realmente funciona mejor y prefiere estar en un servidor con un servidor MAXDOP ancho de 1 .. No me gusta, pero esa es la forma en que lo desarrollaron. ¿Puedes publicar los planes de ejecución reales? Todo lo que veo en ese enlace es el .xdl (gráfico de punto muerto)
Mike Walsh
Hola caballeros, realmente aprecio que se hayan tomado el tiempo, fuera de su apretada agenda para responder. Publicaré tanto los procedimientos como los planes de ejecución para su revisión en el sitio de SkyDrive. Pensé en modificar el código para incluir la opción de consulta MAXDOP (1), sin embargo, hacerlo anulará nuestro soporte con Microsoft. El servidor físico es una configuración ProLiant DL580 G4 MAXDOP es 4 con un total de 8 procesadores físicos y H / T está desactivado.
SQLJarHead
Hola caballeros, he creado un paquete zip con todos los detalles en SkyDrive. Modifiqué el cuerpo de la publicación original para incluir la URL del paquete. Por favor, no me diga cuál es el problema, solo brinde orientación y haga que trabaje para solucionarlo. NOTA: No puedo realizar ningún cambio de código o modificaciones DDL en el esquema subyacente.
SQLJarHead
1
Entonces, no puede cambiar el código y no puede cambiar el esquema, ¿qué otras soluciones espera que presentemos? Si le preocupa anular el soporte de Microsoft, entonces eso significa que tiene soporte de Microsoft, en cuyo caso, dadas todas las restricciones que nos ha dicho que no puede hacer, ¿ha considerado abrir un ticket de soporte con Microsoft?
Aaron Bertrand

Respuestas:

14

A primera vista, parece un punto muerto de búsqueda clásico . Los ingredientes esenciales para este patrón de estancamiento son:

  • una SELECTconsulta que utiliza un índice no agrupado no cubierto con una búsqueda de clave
  • una INSERTconsulta que modifica el índice agrupado y luego el índice no agrupado

La SELECTaccesos el índice no agrupado primero, entonces el índice agrupado. El INSERTacceso al índice agrupado en primer lugar, a continuación, el índice no agrupado. Acceder a los mismos recursos en un orden diferente adquiriendo bloqueos incompatibles es una excelente manera de 'lograr' un punto muerto, por supuesto.

En este caso, la SELECTconsulta es:

Consulta SELECT

... y la INSERTconsulta es:

INSERTAR consulta

Observe el mantenimiento resaltado en verde de los índices no agrupados.

Tendríamos que ver la versión en serie del SELECTplan en caso de que sea muy diferente de la versión paralela, pero como Jonathan Kehayias señala en su guía sobre Manejo de puntos muertos , este patrón de punto muerto en particular es muy sensible al tiempo y a los detalles de implementación de la ejecución de consultas internas. Este tipo de punto muerto a menudo viene y pasa sin una razón externa obvia.

Dado el acceso al sistema en cuestión y los permisos adecuados, estoy seguro de que eventualmente podríamos averiguar exactamente por qué el punto muerto se produce con el plan paralelo pero no con el serial (asumiendo la misma forma general). Líneas posibles de investigación incluyen la comprobación de bucles anidados optimizadas y / o la obtención previa - ambos de los cuales internamente pueden escalar el nivel de aislamiento que REPEATABLE READdurante la duración de la exposición. También es posible que alguna característica de la asignación de rango de búsqueda de índice paralelo contribuya al problema. Si el plan en serie está disponible, podría pasar algún tiempo buscando más detalles, ya que es potencialmente interesante.

La solución habitual para este tipo de interbloqueo es hacer que el índice cubra, aunque la cantidad de columnas en este caso puede hacer que sea poco práctico (y además, se supone que no debemos meternos con esas cosas en SharePoint, según me han dicho). En última instancia, la recomendación para planes solo en serie cuando se usa SharePoint está ahí por una razón (aunque no necesariamente una buena, cuando se trata de eso). Si el cambio en el umbral de costo para el paralelismo soluciona el problema por el momento, esto es bueno. A largo plazo, probablemente buscaría separar las cargas de trabajo, tal vez usando el regulador de recursos para que las consultas internas de SharePoint obtengan el MAXDOP 1comportamiento deseado y la otra aplicación pueda usar el paralelismo.

La cuestión de los intercambios que aparecen en el rastro del punto muerto me parece una pista falsa; simplemente una consecuencia de los hilos independientes que poseen recursos que técnicamente deben aparecer en el árbol. No puedo ver nada que sugiera que los intercambios en sí mismos están contribuyendo directamente al problema de bloqueo.

Paul White 9
fuente
6

Si se trata de un punto muerto de búsqueda clásico , la lista de recursos incluirá tanto el índice agrupado como el índice no agrupado. Por lo general, SELECT mantendrá un bloqueo COMPARTIDO en el índice NC y esperará un bloqueo COMPARTIDO en el CI, mientras que INSERT adquirirá un bloqueo EXCLUSIVO en el CI y esperará un bloqueo EXCLUSIVO en el NC. La lista de recursos en el punto muerto xml enumerará ambos objetos en este caso.

Dado que el gráfico de punto muerto solo involucra el índice NC, podemos descartar esa opción.

Además, si se trataba de un bloqueo muerto debido a la unión de bucle anidado con PREFETCH SIN ORDENAR , el plan de ejecución nos dirá si se utiliza el algoritmo de PREFETCH SIN ORDENAR, lo que nuevamente no es el caso aquí (ver actualización a continuación).

Eso nos deja suponer que este es un punto muerto debido al Plan Paralelo.

El gráfico de punto muerto no se representa correctamente, pero si observa el XML de punto muerto, puede ver que dos hilos de la instrucción SELECT (SPID 690) están involucrados en el punto muerto. El subproceso del consumidor mantiene un bloqueo COMPARTIDO en la PÁGINA 1219645 y espera al productor en el puerto 801f8ed0 (e_waitPipeGetRow). El subproceso productor está esperando un bloqueo compartido en la PÁGINA 1155940.

La instrucción INSERT mantiene un bloqueo IX en la PÁGINA 1155940 y espera un bloqueo IX en la PÁGINA 1219645, lo que resulta en un punto muerto.

Creo que se evitará un punto muerto al usar un plan en serie para la instrucción SELECT, ya que en ningún momento requerirá el bloqueo COMPARTIDO en más de una página. También creo que el plan en serie será casi el mismo que el plan paralelo (sin el operador de paralelismo).

[ACTUALIZADO en base al comentario de Paul]

Aparentemente, el plan está utilizando un algoritmo de bucle anidado optimizado

Eso explica por qué los bloqueos COMPARTIDOS se mantienen hasta el final de la declaración. La LECTURA REPETIBLE combinada con el plan paralelo es más vulnerable al punto muerto que un plan en serie porque el plan paralelo puede adquirir y mantener bloqueos de diferentes rangos de un índice, mientras que el plan en serie adquiere bloqueos de una manera más secuencial.

Roji P Thomas
fuente
Convenido. Si este punto muerto estuviera relacionado con una BÚSQUEDA real, el recurso de espera, para SELECCIONAR, habría hecho referencia al índice agrupado. Pude descartarlo mostrando el encabezado de página para cada recurso de espera (SPID 690 Wait Resource = PAGE: 1155940 | SPID 356 Wait Resource = PAGE 1219645) a través de DBCC PAGE y ambos estaban en el ID de índice 5 (IndexID 5 = EventReceivers_ByContextObjectId) que apunta al índice NC en la tabla especificada (EventReceivers).
SQLJarHead
Señores, gracias de nuevo por tomarse el tiempo para ayudar a analizar este interesante tema. Un par de preguntas: 1.) Roji señala que el SPID paralelo solicita más de una página. No veo eso en ninguno de los planes de ejecución. Mirando el número de filas, para el operador INDEX SEEK, solo un hilo de los dos productores está procesando las filas. ¿Cómo determinó que solicitaba más de una página? (1/2)
SQLJarHead
2.) ¿Un algoritmo de bucle anidado optimizado siempre establecerá el nivel de aislamiento en REAPTABLE READ? He comprobado la salida XML de los planes de ejecución y solo veo lectura confirmada para la conexión SPID. Supongo que esto solo se invoca a nivel del operador del plan solamente. (2/2)
SQLJarHead
El comportamiento de bloqueo de los bucles anidados OPTIMIZADOS es comparable a REPEATABLE READ (mantiene los bloqueos hasta el final de la declaración ), pero no establece de manera explícita el nivel de aislamiento de la transacción en REPEATABLE READ. Creo que eso responde a tu pregunta también. No es que los hilos paralelos soliciten más de una página a la vez, sino que un hilo paralelo mantiene un bloqueo en una página y otro hilo espera un bloqueo en otra página
Roji P Thomas