Database
 sql >> Base de Dados >  >> RDS >> Database

Compreendendo a perda de eventos com eventos estendidos


Minha colega, Erin Stellato, recentemente me fez uma pergunta sobre onde e por que a perda de eventos poderia ocorrer com eventos estendidos. A pergunta foi o resultado de um comentário que alguém fez em uma de suas postagens de blog que afirmava que showplan_xml os eventos não podem ser coletados pelo XE Profiler ou por meio de uma transmissão “ao vivo” dos eventos do servidor. Acontece que eu sei que isso não está correto porque demonstrei rotineiramente os impactos negativos no desempenho do uso do evento post_query_execution_showplan em uma carga de trabalho de produção adicionando o evento na interface do usuário e fazendo com que ele assistisse aos dados ao vivo, então isso iniciou uma discussão mais aprofundada sobre como e quando o Extended Events descartará um evento que foi gerado durante a coleta de dados.

O tamanho do evento é importante


Eventos Estendidos configura o espaço do buffer de memória interna para uma sessão de eventos quando ela é iniciada inicialmente no servidor, e a configuração das opções da sessão de eventos determina o tamanho dos buffers de memória e o tamanho máximo do evento que a sessão de eventos pode coletar. Embora a maioria dos eventos gerados por Extended Events seja relativamente leve e pequena em formato binário, eventos específicos podem gerar uma carga muito maior de dados que precisam ser armazenados em buffer. As opções de sessão de evento padrão resultam em uma configuração de sessão com três buffers de memória interna para armazenar eventos com tamanho de 1.441.587 bytes. O tamanho e o número de buffers de memória para uma sessão de evento podem ser encontrados no DMV sys.dm_xe_sessions enquanto a sessão STATE=START no 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;



Observe que não há buffers grandes para cada uma das sessões de eventos definidas pelo sistema e o tamanho do buffer grande também é definido como zero, que é a configuração padrão. Os buffers grandes para uma sessão de evento são criados apenas quando a opção de sessão MAX_EVENT_SIZE é configurada para a sessão de evento. O valor padrão para essa opção é 0, o que significa que o maior evento que a sessão de eventos pode consumir é o tamanho de um buffer de memória regular, que é de 1.441.587 bytes. Para determinados eventos, como os que produzem o showplan_xml, na verdade é relativamente fácil ter um tamanho de evento maior que o tamanho do buffer de memória padrão para a sessão do evento. Nesses casos, o evento grande seria realmente descartado pela sessão do evento, pois não pode ser colocado em um buffer de memória para despacho.

Controle de perda de evento


Existem três opções de sessão específicas que determinam o tamanho de um evento que uma sessão de eventos pode realmente coletar e uma que controla como os eventos são descartados quando a memória do buffer para a sessão de eventos está cheia ou sob pressão. Todos os quatro são importantes quando falamos sobre a coleta de eventos que podem gerar uma grande carga útil de evento e queremos minimizar a chance de potencialmente descartar um evento. Um exemplo de sessão de evento que estaria propenso a perda de eventos devido à pressão de memória no espaço do buffer para a sessão de eventos está abaixo:
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);

Observação:esta não é uma sessão de evento que eu recomendaria executar em uma carga de trabalho de produção – o volume de dados que ela geraria seria significativo, pois está rastreando cada aquisição e liberação de bloqueio.

Se iniciarmos esta sessão e, em seguida, executarmos o gerador de carga de trabalho AdventureWorks Books Online que está disponível em meu blog em uma instância do SQL Server, a sessão começará a descartar eventos rapidamente devido à geração rápida de eventos e ao atraso na liberação do buffer para o destino event_file que está configurado. O número de eventos que foram descartados por uma sessão de evento pode ser rastreado na DMV sys.dm_xe_sessions se as opções da sessão de evento tiverem sido configuradas com EVENT_RETENTION_MODE =ALLOW_SINGLE_EVENT_LOSS. Se a sessão do evento estiver configurada com EVENT_RETENTION_MODE=ALLOW_MULTIPLE_EVENT_LOSS, então todos os buffers de memória de eventos podem ser eliminados e conta apenas quantos buffers foram eliminados e não o número de eventos individuais que cada buffer continha.
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;



Aqui, podemos ver que 100.521 eventos foram descartados e o maior tamanho de um evento que foi descartado foi de 176 bytes, que é menor que o tamanho do nosso espaço de buffer regular, então estamos apenas atingindo a pressão normal do espaço de memória do buffer. No entanto, se criarmos uma sessão de evento que colete os dois eventos do plano de exibição (consulte este artigo para saber por que isso afetará gravemente o desempenho e não deve ser feito em servidores de produção), juntamente com os eventos de início e conclusão do lote e gerar alguns eventos maiores planos, podemos acionar a perda do evento devido ao tamanho do 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;



Aqui, podemos ver que o large_event_dropped_size é maior que o nosso regular_buffer_size, então isso significa que precisamos alterar a configuração dos nossos buffers de sessão. Se aumentarmos o MAX_MEMORY para a sessão do evento, isso pode aumentar o tamanho de nossos buffers regulares. O valor padrão é de apenas 4 MB, que é de onde vem o tamanho do buffer de 1,4 MB mostrado acima. Se alterarmos para 64 MB para a sessão do evento, o regular_buffer_size terá 22,4 MB, o que acomodaria nosso evento descartado de 3,7 MB. A outra opção é definir a opção MAX_EVENT_SIZE que fornece o large_buffer_size para eventos grandes e é dividido por dois para a sessão.
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);



Então, aqui podemos ver os dois grandes buffers com um tamanho de 33,6 MB e depois de executar o mesmo plano gerando carga de trabalho novamente, não temos eventos descartados para nossa nova sessão CollectsEvents, mas dobramos os eventos descartados para nossa sessão DropsEvents usando os padrões.

Então, aí está; por que determinados eventos podem não ser coletados por uma sessão de eventos, como solucionar problemas quando os eventos estão sendo descartados e como determinar se é o tamanho do evento que está causando o problema. Muitas das sessões que vejo em uso real em sistemas cliente têm os padrões para opções de sessão de eventos, especialmente no que diz respeito à memória. Esta é uma área que, uma vez que você entenda o mecanismo de buffer usado por Extended Events e considere o tamanho dos eventos que podem ser gerados, você começará a fazer alterações na forma como as opções de sessão são definidas para minimizar o potencial de eventos sendo descartado devido a limites de espaço de memória ou restrições de tamanho de evento.