Database
 sql >> Database >  >> RDS >> Database

Comprendere la perdita di eventi con eventi estesi

La mia collega, Erin Stellato, di recente mi ha fatto una domanda su dove e perché potrebbe verificarsi la perdita di eventi con gli eventi estesi. La domanda era il risultato di un commento che qualcuno aveva fatto su uno dei suoi post del blog che affermava che showplan_xml gli eventi non possono essere raccolti da XE Profiler o tramite un flusso "live" degli eventi dal server. Mi capita di sapere che questo non è corretto perché ho regolarmente dimostrato gli impatti negativi sulle prestazioni dell'utilizzo dell'evento post_query_execution_showplan rispetto a un carico di lavoro di produzione aggiungendo l'evento nell'interfaccia utente e facendogli guardare i dati in tempo reale, quindi questo ha avviato una discussione più approfondita su come e quando gli eventi estesi elimineranno un evento che è stato generato durante la raccolta dei dati.

Le dimensioni dell'evento contano

Eventi estesi configura lo spazio del buffer di memoria interna per una sessione di eventi quando viene avviata inizialmente sul server e la configurazione delle opzioni della sessione di eventi determina la dimensione dei buffer di memoria e la dimensione massima dell'evento che la sessione di eventi può raccogliere. Sebbene la maggior parte degli eventi generati da eventi estesi siano relativamente leggeri e di dimensioni ridotte in formato binario, eventi specifici possono generare un carico utile di dati molto più grande che deve essere memorizzato nel buffer. Le opzioni predefinite della sessione di eventi determinano una configurazione di sessione con tre buffer di memoria interni per contenere eventi di dimensioni pari a 1.441.587 byte. La dimensione e il numero di buffer di memoria per una sessione di eventi possono essere trovati nel DMV sys.dm_xe_sessions mentre la sessione STATE=START sul server:

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;

Si noti che non sono presenti buffer di grandi dimensioni per ciascuna sessione di eventi definita dal sistema e anche la dimensione del buffer di grandi dimensioni è impostata su zero, che è la configurazione predefinita. I buffer di grandi dimensioni per una sessione di eventi vengono creati solo quando l'opzione di sessione MAX_EVENT_SIZE è configurata per la sessione di eventi. Il valore predefinito per questa opzione è 0, il che significa che l'evento più grande che la sessione di eventi può effettivamente consumare è la dimensione di un normale buffer di memoria, ovvero 1.441.587 byte. Per alcuni eventi, come quelli che producono showplan_xml, è in realtà relativamente facile avere una dimensione dell'evento maggiore della dimensione del buffer di memoria predefinita per la sessione dell'evento. In questi casi, l'evento di grandi dimensioni verrebbe effettivamente scartato dalla sessione dell'evento poiché non può essere inserito in un buffer di memoria per l'invio.

Controllare la perdita di eventi

Esistono tre opzioni di sessione specifiche che determinano la dimensione di un evento che una sessione di eventi può effettivamente raccogliere e una che controlla il modo in cui gli eventi vengono eliminati quando la memoria del buffer per la sessione di eventi è piena o sotto pressione. Tutti e quattro questi elementi sono importanti quando si parla di raccogliere eventi che potrebbero generare un carico utile di eventi di grandi dimensioni e vogliamo ridurre al minimo la possibilità che potremmo potenzialmente eliminare un evento. Di seguito è riportato un esempio di sessione di eventi che potrebbe essere soggetta a perdita di eventi a causa della pressione della memoria nello spazio buffer per la sessione di eventi:

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:questa non è una sessione di eventi che consiglierei di eseguire su un carico di lavoro di produzione:il volume di dati che genererebbe sarebbe significativo, poiché tiene traccia di ogni acquisizione e rilascio di blocchi.

Se avviamo questa sessione e quindi eseguiamo il generatore di carico di lavoro della documentazione in linea di AdventureWorks disponibile nel mio blog su un'istanza di SQL Server, la sessione inizierà rapidamente a eliminare gli eventi a causa della rapida generazione di eventi e del ritardo nello svuotamento del buffer nella destinazione event_file che è configurato. È possibile tenere traccia del numero di eventi eliminati da una sessione di eventi nella DMV sys.dm_xe_sessions se le opzioni della sessione di eventi sono state configurate con EVENT_RETENTION_MODE =ALLOW_SINGLE_EVENT_LOSS. Se la sessione di eventi è configurata con EVENT_RETENTION_MODE=ALLOW_MULTIPLE_EVENT_LOSS, è possibile eliminare interi buffer di memoria degli eventi e conta solo quanti buffer sono stati eliminati e non il numero di singoli eventi contenuti in ciascun buffer.

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;

Qui possiamo vedere che 100.521 eventi sono stati eliminati e la dimensione massima di un evento che è stato eliminato era di 176 byte, che è inferiore alla dimensione del nostro normale spazio di buffer, quindi stiamo solo colpendo la normale pressione dello spazio di memoria del buffer. Tuttavia, se creiamo una sessione di eventi che raccolga i due eventi showplan (consulta questo articolo per sapere perché ciò influirà negativamente sulle prestazioni e non dovrebbe essere eseguito sui server di produzione), insieme agli eventi di avvio e completamento del batch e genererà alcuni eventi più grandi piani, possiamo attivare la perdita di eventi a causa delle dimensioni dell'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;

Qui, possiamo vedere che la dimensione_evento_ridotta_più_grande è maggiore della dimensione_del_buffer_normale, quindi questo significa che dobbiamo modificare la configurazione dei nostri buffer di sessione. Se aumentiamo MAX_MEMORY per la sessione di eventi, può aumentare la dimensione dei nostri buffer regolari. Il valore predefinito è solo 4 MB, da cui deriva la dimensione del buffer di 1,4 MB mostrata sopra. Se cambiamo questo valore in 64 MB per la sessione dell'evento, la dimensione del buffer_normale avrà una dimensione di 22,4 MB che potrebbe ospitare il nostro evento eliminato da 3,7 MB. L'altra opzione è impostare l'opzione MAX_EVENT_SIZE che fornisce large_buffer_size per eventi di grandi dimensioni ed è divisa per due per la sessione.

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);

Quindi qui possiamo vedere i due grandi buffer con una dimensione di 33,6 MB e dopo aver eseguito lo stesso piano generando nuovamente il carico di lavoro non abbiamo eventi eliminati per la nostra nuova sessione CollectsEvents, ma abbiamo raddoppiato gli eventi eliminati per la nostra sessione DropsEvents utilizzando le impostazioni predefinite.

Così il gioco è fatto; perché determinati eventi potrebbero non essere raccolti da una sessione di eventi, come risolvere i problemi quando gli eventi vengono eliminati e come determinare se è la dimensione dell'evento a causare il problema. Molte delle sessioni che vedo nell'uso effettivo sui sistemi client hanno le impostazioni predefinite per le opzioni della sessione di eventi, in particolare per quanto riguarda la memoria. Questa è un'area in cui, una volta compreso il meccanismo di buffering utilizzato dagli eventi estesi e quindi considerata la dimensione degli eventi che potrebbero essere potenzialmente generati, inizierai ad apportare modifiche alla modalità di definizione delle opzioni di sessione per ridurre al minimo il potenziale di eventi viene eliminato a causa di limiti di spazio di memoria o di dimensioni dell'evento.