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

Comprender la pérdida de eventos con eventos extendidos

Mi colega, Erin Stellato, recientemente me hizo una pregunta sobre dónde y por qué podría ocurrir la pérdida de eventos con eventos extendidos. La pregunta fue el resultado de un comentario que alguien había hecho en una de sus publicaciones de blog que afirmaba que showplan_xml XE Profiler no puede recopilar eventos ni a través de una transmisión "en vivo" de los eventos desde el servidor. Sé que esto no es correcto porque he demostrado rutinariamente los impactos negativos en el rendimiento del uso del evento post_query_execution_showplan contra una carga de trabajo de producción al agregar el evento en la interfaz de usuario y hacer que mire los datos en vivo, por lo que esto inició una discusión más profunda. sobre cómo y cuándo Extended Events descartará un evento que se haya generado durante la recopilación de datos.

El tamaño del evento importa

Extended Events configura el espacio del búfer de la memoria interna para una sesión de eventos cuando se inicia inicialmente en el servidor, y la configuración de las opciones de la sesión de eventos determina el tamaño de los búferes de memoria y el tamaño máximo de eventos que puede recopilar la sesión de eventos. Si bien la mayoría de los eventos generados por Extended Events son relativamente livianos y pequeños en formato binario, los eventos específicos pueden generar una carga de datos mucho mayor que debe almacenarse en búfer. Las opciones de sesión de eventos predeterminadas dan como resultado una configuración de sesión con tres búferes de memoria interna para almacenar eventos que tienen un tamaño de 1 441 587 bytes. El tamaño y la cantidad de búferes de memoria para una sesión de eventos se pueden encontrar en sys.dm_xe_sessions DMV mientras la sesión STATE=START en el servidor:

SELECT
    s.name, 
    s.total_regular_buffers,
    s.regular_buffer_size,
    s.total_large_buffers,
    s.large_buffer_size,
    s.total_buffer_size
FROM sys.dm_xe_sessions AS s;

Tenga en cuenta que no hay búfer grandes para cada una de las sesiones de eventos definidas por el sistema, y ​​el tamaño del búfer grande también se establece en cero, que es la configuración predeterminada. Los búfer grandes para una sesión de eventos solo se crean cuando la opción de sesión MAX_EVENT_SIZE está configurada para la sesión de eventos. El valor predeterminado para esta opción es 0, lo que significa que el evento más grande que la sesión de eventos puede consumir realmente es del tamaño de un búfer de memoria normal, que es 1 441 587 bytes. Para ciertos eventos, como los que producen showplan_xml, en realidad es relativamente fácil tener un tamaño de evento mayor que el tamaño del búfer de memoria predeterminado para la sesión de eventos. En estos casos, la sesión de eventos descartaría el evento grande, ya que no se puede colocar en un búfer de memoria para enviarlo.

Control de pérdida de eventos

Hay tres opciones de sesión específicas que determinan el tamaño de un evento que una sesión de eventos puede recopilar y una que controla cómo se eliminan los eventos cuando la memoria intermedia para la sesión de eventos está llena o bajo presión. Los cuatro son importantes cuando hablamos de recopilar eventos que podrían generar una gran carga útil de eventos y queremos minimizar la posibilidad de que podamos descartar un evento. A continuación se muestra un ejemplo de sesión de eventos que sería propensa a la pérdida de eventos debido a la presión de la memoria en el espacio del búfer para la sesión de eventos:

CREATE EVENT SESSION [Locks] ON SERVER 
ADD EVENT sqlserver.lock_acquired,
ADD EVENT sqlserver.lock_released
ADD TARGET package0.event_file(SET filename=N'Locks',max_file_size=(5),max_rollover_files=(4))
WITH (MAX_MEMORY=4096 KB,
MEMORY_PARTITION_MODE=NONE,
EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,
MAX_EVENT_SIZE=0 KB);

Nota:esta no es una sesión de evento que recomendaría ejecutar en una carga de trabajo de producción:el volumen de datos que generaría sería significativo, ya que realiza un seguimiento de cada adquisición y liberación de bloqueos.

Si comenzamos esta sesión y luego ejecutamos el generador de carga de trabajo de AdventureWorks Books Online que está disponible en mi blog en una instancia de SQL Server, la sesión comenzará a descartar eventos rápidamente debido a la rápida generación de eventos y la demora en el vaciado del búfer al destino event_file que está configurado. La cantidad de eventos descartados por una sesión de eventos se puede rastrear en sys.dm_xe_sessions DMV si las opciones de la sesión de eventos se configuraron con EVENT_RETENTION_MODE =ALLOW_SINGLE_EVENT_LOSS. Si la sesión de eventos está configurada con EVENT_RETENTION_MODE=ALLOW_MULTIPLE_EVENT_LOSS, se pueden descartar todos los búferes de memoria de eventos y solo cuenta cuántos búferes se descartaron y no la cantidad de eventos individuales que contenía cada búfer.

SELECT
   s.name, 
   s.total_regular_buffers,
   s.regular_buffer_size,
   s.total_large_buffers,
   s.large_buffer_size,
   s.dropped_event_count,
   s.dropped_buffer_count,
   s.largest_event_dropped_size
FROM sys.dm_xe_sessions AS s;

Aquí, podemos ver que se eliminaron 100 521 eventos y que el tamaño más grande de un evento que se eliminó fue de 176 bytes, que es más pequeño que el tamaño de nuestro espacio de búfer normal, por lo que solo estamos alcanzando la presión de espacio de memoria de búfer normal. Sin embargo, si creamos una sesión de eventos que recopile los dos eventos del plan de presentación (consulte este artículo para saber por qué esto tendrá un impacto negativo en el rendimiento y no se debe hacer en los servidores de producción), junto con los eventos de inicio y finalización del lote y generar algunos eventos más grandes. planes, podemos desencadenar la pérdida de eventos debido al tamaño del evento.

CREATE EVENT SESSION [DropsEvents] ON SERVER 
ADD EVENT sqlserver.query_post_execution_showplan,
ADD EVENT sqlserver.query_pre_execution_showplan,
ADD EVENT sqlserver.sql_batch_completed,
ADD EVENT sqlserver.sql_batch_starting;

Aquí, podemos ver que el tamaño más grande del evento caído es mayor que nuestro tamaño normal del búfer, lo que significa que necesitamos cambiar la configuración de nuestros búferes de sesión. Si aumentamos MAX_MEMORY para la sesión de eventos, puede aumentar el tamaño de nuestros búfer regulares. El valor predeterminado es solo 4 MB, que es de donde proviene el tamaño de búfer de 1,4 MB que se muestra arriba. Si cambiamos esto para que sea de 64 MB para la sesión del evento, el tamaño del búfer regular será de 22,4 MB, lo que acomodaría nuestro evento descartado de 3,7 MB. La otra opción es establecer la opción MAX_EVENT_SIZE, que proporciona el tamaño de búfer grande para eventos grandes y se divide por dos para la sesión.

CREATE EVENT SESSION [CollectsEvents] ON SERVER 
ADD EVENT sqlserver.query_post_execution_showplan,
ADD EVENT sqlserver.query_pre_execution_showplan,
ADD EVENT sqlserver.sql_batch_completed,
ADD EVENT sqlserver.sql_batch_starting
WITH (MAX_MEMORY=65536 KB,MAX_EVENT_SIZE=65536 KB,MEMORY_PARTITION_MODE=NONE);

Así que aquí podemos ver los dos búferes grandes con un tamaño de 33,6 MB y después de ejecutar el mismo plan generando carga de trabajo nuevamente, no tenemos eventos descartados para nuestra nueva sesión de CollectsEvents, pero hemos duplicado los eventos descartados para nuestra sesión de DropsEvents utilizando los valores predeterminados.

Entonces, ahí lo tienes; por qué es posible que una sesión de eventos no recopile ciertos eventos, cómo solucionar problemas cuando se descartan eventos y cómo determinar si es el tamaño del evento lo que está causando el problema. Muchas de las sesiones que veo en uso real en los sistemas cliente tienen los valores predeterminados para las opciones de sesión de eventos, especialmente en lo que respecta a la memoria. Esta es un área en la que, una vez que comprenda el mecanismo de almacenamiento en búfer que utilizan los eventos extendidos, y luego considere el tamaño de los eventos que podrían generarse potencialmente, comenzará a realizar cambios en la forma en que se definen las opciones de la sesión para minimizar la posibilidad de eventos. se descarta debido a límites de espacio de memoria o restricciones de tamaño de evento.