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
fuente
proc_InsertEventReceiver
yproc_InsertContextEventReceiver
hacemos 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?Respuestas:
A primera vista, parece un punto muerto de búsqueda clásico . Los ingredientes esenciales para este patrón de estancamiento son:
SELECT
consulta que utiliza un índice no agrupado no cubierto con una búsqueda de claveINSERT
consulta que modifica el índice agrupado y luego el índice no agrupadoLa
SELECT
accesos el índice no agrupado primero, entonces el índice agrupado. ElINSERT
acceso 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
SELECT
consulta es:... y la
INSERT
consulta es:Observe el mantenimiento resaltado en verde de los índices no agrupados.
Tendríamos que ver la versión en serie del
SELECT
plan 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 READ
durante 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 1
comportamiento 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.
fuente
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.
fuente