sql >> Base de Datos >  >> RDS >> Database

Introducción a los pestillos

En algunos de mis artículos anteriores aquí sobre el ajuste del rendimiento, analicé varios tipos de espera y cómo son indicativos de varios cuellos de botella de recursos. Estoy comenzando una nueva serie sobre escenarios en los que un mecanismo de sincronización llamado pestillo es un cuello de botella de rendimiento, y específicamente pestillos que no son de página. En esta publicación inicial, explicaré por qué se requieren pestillos, qué son en realidad y cómo pueden ser un cuello de botella.

¿Por qué se necesitan pestillos?

Es un principio básico de la informática que cada vez que existe una estructura de datos en un sistema de subprocesos múltiples, la estructura de datos debe protegerse de alguna manera. Esta protección otorga las siguientes condiciones:

  1. (Garantizado) Un subproceso no puede cambiar una estructura de datos mientras otro subproceso lo está leyendo
  2. (Garantizado) Un subproceso no puede leer una estructura de datos mientras otro subproceso la está cambiando
  3. (Garantizado) Una estructura de datos no puede ser modificada por dos o más subprocesos al mismo tiempo
  4. (Opcional) Permita que dos o más subprocesos lean la estructura de datos al mismo tiempo
  5. (Opcional) Permita que los subprocesos se pongan en cola de manera ordenada para acceder a la estructura de datos

Esto se puede hacer de varias maneras, incluyendo:

  • Un mecanismo que solo permite que un subproceso a la vez tenga acceso a la estructura de datos. SQL Server implementa este mecanismo y lo llama spinlock. Esto permite #1, #2 y #3 arriba.
  • Un mecanismo que permite que varios subprocesos lean la estructura de datos al mismo tiempo (es decir, tienen acceso compartido), permite que un solo subproceso obtenga acceso exclusivo a la estructura de datos (con exclusión de todos los demás subprocesos) e implementa una forma justa de hacer cola para acceder. SQL Server implementa este mecanismo y lo llama pestillo. Esto permite las cinco condiciones anteriores.

Entonces, ¿por qué SQL Server usa spinlocks y latches? Se accede a algunas estructuras de datos con tanta frecuencia que un pestillo es simplemente demasiado costoso y, por lo tanto, se usa un spinlock muy liviano en su lugar. Dos ejemplos de tales estructuras de datos son la lista de búferes libres en el grupo de búferes y la lista de bloqueos en el administrador de bloqueos.

¿Qué es un pestillo?

Un pestillo es un mecanismo de sincronización que protege una sola estructura de datos y existen tres tipos amplios de pestillo en SQL Server:

  1. Pestillos que protegen una página de archivo de datos mientras se lee desde el disco. Estos aparecen mientras espera PAGEIOLATCH_XX, y los discutí en esta publicación.
  2. Pestillos que protegen el acceso a una página de archivo de datos que ya está en la memoria (una página de 8 KB en el grupo de búfer es en realidad solo una estructura de datos). Estos aparecen mientras PAGELATCH_XX espera, y los discutí en esta publicación.
  3. Pestillos que protegen las estructuras de datos que no son de página. Estos aparecen como esperas de LATCH_SH y LATCH_EX.

En esta serie, nos vamos a concentrar en el tercer tipo de pestillos.

Un pestillo es en sí mismo una pequeña estructura de datos y puede pensar que tiene tres componentes:

  • Una descripción del recurso (de lo que está protegiendo)
  • Un campo de estado que indica en qué modos se mantiene actualmente el latch, cuántos subprocesos mantienen el latch en ese modo y si hay subprocesos en espera (además de otras cosas de las que no tenemos que preocuparnos)
  • Una cola de subprocesos de tipo primero en entrar, primero en salir que esperan acceso a la estructura de datos y qué modos de acceso están esperando (llamada cola de espera)

Para los pestillos que no son de página, nos limitaremos a considerar solo los modos de acceso SH (compartir) para leer la estructura de datos y EX (exclusivo) para cambiar la estructura de datos. Hay otros modos más exóticos, pero rara vez se usan y no aparecerán como puntos de disputa, así que fingiré que no existen durante el resto de esta discusión.

Algunos de ustedes pueden saber que también existen complicaciones más profundas en torno a los superlatches/sublatches y la partición de latch para la escalabilidad, pero no necesitamos llegar a esa profundidad para los propósitos de esta serie.

Adquirir un pestillo

Cuando un subproceso quiere adquirir un latch, mira el estado del latch.

Si el subproceso desea adquirir el latch en modo EX, solo puede hacerlo si no hay subprocesos que mantengan el latch en ningún modo. Si ese es el caso, el subproceso adquiere el pestillo en modo EX y establece el estado para indicarlo. Si hay uno o más subprocesos que ya tienen el pestillo, el subproceso establece el estado para indicar que hay un subproceso en espera, ingresa al final de la cola de espera y luego se suspende (en la lista de espera del programador en el que se encuentra). ) esperando LATCH_EX.

Si el subproceso desea adquirir el pestillo en modo SH, solo puede hacerlo si ningún subproceso mantiene el pestillo o los únicos subprocesos que sostienen el pestillo están en modo SH *y* no hay subprocesos esperando para adquirir el pestillo. Si ese es el caso, el subproceso adquiere el pestillo en modo SH, establece el estado para indicarlo e incrementa el recuento de subprocesos que mantienen el pestillo. Si el latch se mantiene en modo EX o hay uno o más subprocesos en espera, entonces el subproceso establece el estado para indicar que hay un subproceso en espera, ingresa al final de la cola de espera y luego se suspende esperando LATCH_SH.

La verificación de subprocesos en espera se realiza para garantizar la equidad con un subproceso que espera el pestillo en modo EX. Solo tendrá que esperar a que los subprocesos mantengan el pestillo en modo SH que adquirieron el pestillo antes de que comenzara a esperar. Sin esa verificación, puede ocurrir un término informático llamado "inanición", cuando un flujo constante de subprocesos que adquieren el pestillo en modo SH evita que el subproceso en modo EX pueda adquirir el pestillo.

Liberar un pestillo

Si el subproceso mantiene el pestillo en modo EX, anula el estado que muestra que el pestillo está retenido en modo EX y luego verifica si hay subprocesos en espera.

Si el subproceso mantiene el pestillo en modo SH, disminuye el recuento de subprocesos en modo SH. Si el recuento ahora es distinto de cero, el hilo de liberación se realiza con el pestillo. Si el conteo *es* ahora cero, anula el estado que muestra que el pestillo se mantiene en modo SH y luego verifica si hay subprocesos en espera.

Si no hay hilos esperando, el hilo de liberación se realiza con el pestillo.

Si el jefe de la cola de espera está esperando el modo EX, el subproceso de liberación hace lo siguiente:

  • Establece el estado para mostrar que el pestillo se mantiene en modo EX
  • Elimina el subproceso en espera del encabezado de la cola y lo establece como propietario del latch
  • Señala al subproceso en espera que es el propietario y que ahora se puede ejecutar (al mover conceptualmente el subproceso en espera de la lista de espera en su programador a la cola ejecutable en el programador)
  • Y se hace con el pestillo

Si el jefe de la cola de espera está esperando en modo SH (que solo puede ser el caso si el subproceso de liberación estaba en modo EX), el subproceso de liberación hace lo siguiente:

  • Establece el estado para mostrar que el pestillo se mantiene en modo SH
  • Para todos los subprocesos en la cola de espera que están esperando el modo SH
    • Elimina el hilo en espera del principio de la cola
    • Aumenta la cantidad de subprocesos que sujetan el pestillo
    • Señala al subproceso en espera que es un propietario y ahora se puede ejecutar
  • Y se hace con el pestillo

¿Cómo pueden ser los pestillos un punto de conflicto?

A diferencia de los bloqueos, los pestillos generalmente solo se mantienen durante la operación de lectura o cambio, por lo que son bastante livianos, pero debido a la incompatibilidad SH vs. EX, pueden ser un punto de conflicto tan grande como los bloqueos. Esto puede suceder cuando muchos subprocesos intentan adquirir un latch en modo EX (solo uno a la vez puede hacerlo) o cuando muchos subprocesos intentan adquirir un latch en modo SH y otro subproceso mantiene el latch en modo EX.

Resumen

Cuantos más subprocesos en el sistema compitan por un latch "caliente", mayor será la contención y más negativo será el efecto en el rendimiento de la carga de trabajo. Es probable que haya oído hablar de problemas conocidos de contención de pestillos, por ejemplo, en torno a mapas de bits de asignación de tempdb, pero la contención también puede ocurrir para pestillos que no son de página.

Ahora que le brindé suficientes antecedentes para comprender los latches y cómo funcionan, en los próximos artículos examinaré algunos problemas reales de contención de latch que no son de página y explicaré cómo prevenirlos o solucionarlos.