SQL Server 2008

Solução avançada de problemas com o Extended Events

Paul S. Randal

 

Visão geral:

  • Por que a solução de problemas é necessária
  • Ferramentas de solução de problemas no SQL Server
  • Visão geral e arquitetura do Extended Events
  • Usando o Extended Events

Conteúdo

Solução de problemas no SQL Server 2005
Extended Events
Considerações sobre desempenho
A vida de um evento
Usando o Extended Events
A sessão system_health do Extended Events
Conclusão

Os administradores de bancos de dados do SQL Server em todo o mundo têm um problema que parece não acabar nunca: a solução de problemas, sendo que a imensa maioria visa encontrar a solução de algum tipo de problema de desempenho. Ao longo do tempo, mesmo o sistema de aplicativos projetado e testado com o máximo cuidado sofrerá alterações que poderão levar a significativos problemas de desempenho.

Por exemplo, a carga de trabalho pode mudar (como o número de usuários simultâneos, as consultas executadas e a emissão de novos relatórios de fim de mês), o volume de dados processados pode aumentar, o hardware no qual o sistema é executado pode mudar (como o número de núcleos de processadores, quantidade de memória disponível no servidor e capacidade do subsistema de E/S) e novas cargas de trabalho simultâneas podem surgir (como replicação transacional, espelhamento de banco de dados e captura de dados de alteração).

Mas esses não são os únicos problemas que ocorrem. Ao projetar e testar sistemas de aplicativos, freqüentemente são encontrados problemas imprevistos no design, os quais também exigem solução de problemas. É óbvio que, independentemente do período do ciclo de vida do aplicativo no qual o problema é descoberto, a solução de problemas deve ser executada para identificar a causa e a solução.

Um sistema de aplicativos complexo terá muitos componentes de hardware e software que precisarão ser analisados, mas minha preocupação é com o SQL Server. Sem considerar as várias metodologias de solução de problemas de desempenho (o que seria uma discussão bem além do escopo deste artigo), quais são as ferramentas necessárias para a solução de problemas no SQL Server?

Solução de problemas no SQL Server 2005

Nas últimas versões do SQL Server, a seleção de ferramentas disponíveis para solução de problemas de desempenho aumentou consideravelmente. O SQL Server sempre teve muitos comandos DBCC (comando do console de banco de dados) disponíveis para proporcionar uma visão do que estava acontecendo nas várias partes do mecanismo de banco de dados. Além disso, existe o SQL Server Profiler e o uso programático do mecanismo SQL Trace subjacente.

Embora o SQL Server tenha oferecido continuamente avanços para a solução de problemas, essas opções têm, elas mesmas, alguns problemas. O pós-processamento da saída do DBCC é complicado, já que você precisa despejar os resultados em uma tabela provisória antes de poder fazer qualquer coisa com eles. E a execução do SQL Trace/Profiler pode causar degradação do desempenho, caso esteja configurado inadequadamente (como rastrear todos os eventos Lock: Acquired e Lock: Released em um sistema ocupado e esquecer de aplicar o filtro nas colunas DatabaseId e ObjectId do evento). A captura de tela da Figura 1 mostra uma caixa de diálogo sendo usada para configurar um filtro de um novo rastreamento.

fig01.gif

Figura 1 Configurando um filtro no SQL Server 2008 Profiler

O SQL Server 2005 adicionou funções e exibições de gerenciamento dinâmico (conhecidas coletivamente como DMVs) como um meio de obter informações fora do mecanismo de banco de dados. As DMVs substituíram alguns comandos DBCC, tabelas de sistema e procedimentos armazenados, e revelaram muitas áreas novas do funcionamento do mecanismo. Esses DMVs são comandos poderosos que podem ser compostos — podendo ser usados em instruções T-SQL complexas que filtram e pós-processam os resultados de DMV.

Por exemplo, o código mostrado na Figura 2 retorna apenas a fragmentação e a densidade de página (ambas arredondadas) dos níveis de folha de todos os índices de um banco de dados, com um filtro no nível de fragmentação. Isso não poderia ser feito facilmente usando o meu antigo comando DBCC SHOWCONTIG. Para obter mais informações sobre DMV, consulte "Exibições e funções de gerenciamento dinâmico (Transact-SQL)". Além disso, o SQL Server 2005 adicionou inúmeros outros recursos que podiam ser usados para solução de problemas, inclusive gatilhos DDL (linguagem de definição de dados) e notificações de eventos.

Figura 2 Usando DMVs para obter resultados eficazes

SELECT
  OBJECT_NAME (ips.[object_id]) AS 'Object Name',
  si.name AS 'Index Name',
  ROUND (ips.avg_fragmentation_in_percent, 2) AS 'Fragmentation',
  ips.page_count AS 'Pages',
  ROUND (ips.avg_page_space_used_in_percent, 2) AS 'Page Density'
FROM sys.dm_db_index_physical_stats (
  DB_ID ('SQLskillsDB'), NULL, NULL, NULL, 'DETAILED') ips
CROSS APPLY sys.indexes si
WHERE
  si.object_id = ips.object_id
  AND si.index_id = ips.index_id
  AND ips.index_level = 0 -- only the leaf level
  AND ips.avg_fragmentation_in_percent > 10; -- filter on fragmentation
GO

Várias equipes da Microsoft também forneceram ferramentas úteis de solução de problemas de desempenho, como o utilitário SQLdiag, os utilitários RML para SQL Server, os Relatórios do painel (dashboard) de desempenho do SQL Server 2005 e DMVStats. Existe também um provedor de ETW (Rastreamento de Eventos do Windows) para o SQL Server 2005, que permite que os eventos SQL Trace sejam integrados a eventos de outras partes do Windows.

Embora o SQL Server 2005 tenha dado grandes passos para aumentar a capacidade de os administradores de bancos de dados solucionarem os problemas do mecanismo de banco de dados, ainda havia muitos cenários em que era quase impossível solucionar problemas efetivamente. Em um exemplo citado com freqüência, algumas consultas usam quantidades excessivas de recursos de CPU, mas as DMVs não fornecem informações suficientes para identificar quais consultas ad hoc são as culpadas. Mas, ao contrário do SQL Server 2005, o SQL Server 2008 é capaz de enfrentar tais limitações com um novo recurso chamado SQL Server Extended Events.

Extended Events

Os recursos do sistema Extended Events vão muito além dos de qualquer mecanismo de solução de problemas e de rastreamento de eventos que o SQL Server já tenha fornecido antes. Na minha opinião, os destaques do sistema Extended Events são os seguintes:

  • Os eventos são disparados sincronizadamente, mas podem ser processados de maneira síncrona ou assíncrona.
  • Qualquer destino pode consumir qualquer evento, e qualquer ação pode estar correlacionada com qualquer evento, permitindo um sistema de gerenciamento profundo.
  • Os predicados "inteligentes" permitem criar regras complexas usando a lógica booleana.
  • Você pode ter controle total das sessões Extended Events usando Transact-SQL.
  • Você pode monitorar o código de desempenho crítico sem afetar o desempenho.

Antes de continuar, reservarei uns momentos para definir alguns itens da nova terminologia.

Evento Um evento é um ponto definido no código. Alguns exemplos são: o ponto em que uma instrução T-SQL terminou a execução ou o ponto em que a obtenção de um bloqueio foi concluída. Cada evento tem uma carga definida (o conjunto de colunas retornado pelo evento) e é definido usando o modelo ETW (em que cada evento retorna um canal e uma palavra-chave como parte da carga) para permitir a integração com o ETW. O SQL Server 2008 foi lançado inicialmente com 254 eventos definidos e espera-se que outros sejam adicionados ao longo do tempo.

Veja a lista dos eventos definidos usando o seguinte código:

SELECT xp.[name], xo.*
FROM sys.dm_xe_objects xo, sys.dm_xe_packages xp
WHERE xp.[guid] = xo.[package_guid]
  AND xo.[object_type] = 'event'
ORDER BY xp.[name];

E descubra a carga de um evento específico usando este código:

SELECT * FROM sys.dm_xe_object_columns
  WHERE [object_name] = 'sql_statement_completed';
GO

Observe que o sistema Extended Events tem um conjunto abrangente de DMVs informativas que descrevem todos os eventos, destinos e outros. Para obter mais detalhes, consulte "Exibições de gerenciamento dinâmico do SQL Server Extended Events".

Predicados Predicados são o método usado para filtrar eventos, usando um conjunto de regras lógicas, antes que os eventos sejam consumidos. Os predicados podem ser simples, como verificar se uma das colunas retornadas na carga do evento tem determinado valor (por exemplo, filtrar eventos lock-acquired pela identificação do objeto).

Eles também oferecem recursos avançados, como contar o número de vezes que um evento ocorreu durante a sessão e só permitir que o evento seja consumido depois de uma ocorrência, ou atualizar dinamicamente o próprio predicado para suprimir o consumo de eventos que tenham dados similares.

Os predicados podem ser escritos usando a lógica booleana, de modo que eles criem um curto-circuito o mais breve possível. Isso permite que seja processado o mínimo de processamento sincronizado antes que se determine se o evento será consumido ou não.

Ação Uma ação é um conjunto de comandos executados sincronizadamente antes que um evento seja consumido. Qualquer ação pode ser vinculada a qualquer evento. Geralmente, as ações reúnem mais dados para acrescentar à carga do evento (como uma pilha do T-SQL ou um plano de execução de consultas) ou executam alguns cálculos que são acrescentados à carga do evento.

Como podem ser dispendiosas, as ações de um evento só são executadas depois de algum predicado ser avaliado — não haveria nenhum ponto para executar sincronizadamente uma ação se fosse então determinado que o evento não seria consumido. Uma lista das ações predefinidas pode ser encontrada usando-se o seguinte código:

SELECT xp.[name], xo.*
FROM sys.dm_xe_objects xo, sys.dm_xe_packages xp
WHERE xp.[guid] = xo.[package_guid]
  AND xo.[object_type] = 'action'
ORDER BY xp.[name];

Destino Um destino simplesmente fornece um modo de consumir eventos, e qualquer destino pode consumir qualquer evento (ou, pelo menos, desfazer-se dele se não houver nada para o destino fazer — como um destino de auditoria recebendo um evento sem auditoria). Os destinos podem consumir eventos de maneira síncrona (por exemplo, o código que disparou o evento espera que o evento seja consumido) ou assíncrona.

Os destinos abrangem desde consumidores simples, como arquivos de eventos e buffers em anel, até consumidores mais complexos que têm a capacidade de executar correlação de eventos. Você pode encontrar a lista de destinos disponíveis usando o seguinte código:

SELECT xp.[name], xo.*
FROM sys.dm_xe_objects xo, sys.dm_xe_packages xp
WHERE xp.[guid] = xo.[package_guid]
  AND xo.[object_type] = 'target'
ORDER BY xp.[name];

Para obter mais detalhes sobre destinos, consulte "Destinos do SQL Server Extended Events".

Pacote Um pacote é um contêiner que define objetos do Extended Events (como eventos, ações e destinos). Um pacote está contido no módulo (como um executável ou uma DLL) que ele descreve, como mostrado na Figura 3.

Figura 3 O relacionamento entre módulos, pacotes e objetos do Extended Events

Quando um pacote é registrado no mecanismo Extended Events, todos os objetos definidos por ele ficam disponíveis para uso. Para obter mais informações sobre pacotes e obter uma lista completa da terminologia do Extended Events, consulte "Pacotes do SQL Server Extended Events."

Sessão Uma sessão é um modo de vincular objetos do Extended Events para processamento — um evento com uma ação para ser consumido por um destino. Uma sessão pode vincular objetos de qualquer pacote registrado, e qualquer número de sessões pode usar o mesmo evento, a mesma ação etc. Veja quais sessões do Extended Events estão definidas usando o seguinte código:

SELECT * FROM sys.dm_xe_sessions;
Go

As sessões são criadas, descartadas, alteradas, interrompidas e iniciadas usando-se comandos T-SQL. Como você pode imaginar, isso oferece muita flexibilidade, até mesmo a capacidade de alterar dinamicamente uma sessão com base em análise programática dos dados capturados pela própria sessão. Para aprender sobre sessões, consulte "Sessões do SQL Server Extended Events".

Considerações sobre desempenho

Quando você monta uma sessão do Extended Events usando CREATE EVENT SESSION, precisa ter cuidado para configurar corretamente algumas opções, pois elas podem inadvertidamente afetar o desempenho. Sua primeira decisão é se os eventos devem ser consumidos de maneira síncrona ou assíncrona. E como se poderia esperar, os destinos síncronos têm maior efeito sobre o desempenho do código monitorado do que os destinos assíncronos.

Como expliquei anteriormente, quando um evento é consumido de maneira síncrona, o código que disparou o evento tem de esperar até que o evento tenha sido consumido. Obviamente, se o consumo do evento for um processo complicado, isso poderá retardar o código.

Por exemplo, em um sistema ocupado atendendo a milhares de pequenas transações por segundo, o consumo síncrono de um evento sql_statement_completed com uma ação para capturar um plano de consultas terá, muito provavelmente, um impacto negativo no desempenho. Além disso, lembre-se de que os predicados são sempre executados de maneira síncrona, portanto, deve-se tomar cuidado para não criar predicados excessivamente complexos para eventos disparados por código de desempenho crítico.

Por outro lado, talvez você seja forçado a consumir eventos de maneira síncrona. Para contar as ocorrências de um evento específico, a maneira mais fácil será, provavelmente, usar o destino synchronous_event_counter.

O segundo item que você deve considerar é como configurar o buffer do evento, caso decida usar destinos assíncronos. O valor padrão de memória disponível para o buffer de eventos é de 4 MB. A latência de envio padrão entre o disparo de um evento e o subseqüente consumo por um destino é de 30 segundos. Se, digamos, você quiser produzir alguma estatística do evento a cada 10 segundos, precisará ajustar a latência.

O modo pelo qual você quer fazer a partição da memória usada para o buffer está vinculado às configurações do buffer de eventos. O padrão é criar um conjunto de buffers para toda a instância. Em máquinas SMP (multiprocessador simétrico) e NUMA (acesso não-uniforme à memória), isso pode levar a problemas de desempenho com processadores que precisem esperar pelo acesso à memória.

O terceiro ponto a considerar é como você quer lidar com a perda de eventos. Ao definir a sessão do Extended Events, é possível especificar se os eventos podem ser "perdidos". Isso significa que, se não houver no buffer memória suficiente para um evento, ele será simplesmente descartado. O padrão é permitir que eventos únicos sejam descartados, mas também é possível permitir que buffers inteiros de eventos sejam perdidos (para sessões em que os buffers ficam cheios muito rapidamente) ou mesmo especificar que nenhum evento pode ser perdido.

A última opção deve ser usada com muita cautela, pois ela força o código disparador do evento a esperar até que haja memória suficiente no buffer para armazenar o evento. Configurar essa opção quase sempre tem efeito prejudicial no desempenho. Observe que se você, acidentalmente, definir essa opção como ligada, o servidor deverá permanecer com suficiente capacidade de resposta para permitir que você desative a configuração.

Geralmente, você desejará considerar essas configurações em conjunto. E não existe efetivamente uma prática recomendada geral que eu possa indicar, a não ser a de você dar muita atenção a elas, ou poderá enfrentar problemas de desempenho. Você também pode obter mais informações sobre essas opções em CREATE EVENT SESSION (T-SQL).

A vida de um evento

Quando a sessão do Extended Events tiver sido definida e iniciada, o processamento continuará normalmente até que o código sob monitoramento chegue a um evento. As etapas percorridas pelo sistema Extended Events estão descritas na Figura 4. As etapas são as seguintes:

  1. É feita uma verificação para observar se as sessões do Extended Events estão monitorando o evento. Caso não estejam, o controle é devolvido ao código que contém o evento, e o processamento continua.
  2. A carga do evento foi determinada e todas as informações necessárias estão reunidas na memória — em outras palavras, a carga do evento está construída.
  3. Se houver predicados definidos para o evento, eles serão executados. Nesse ponto, o resultado do predicado talvez seja que o evento não deve ser consumido. Se for esse o caso, o controle será devolvido ao código que contém o evento, e o processamento continuará.
  4. Agora o sistema sabe que o evento será consumido; assim, ele executa todas as ações vinculadas ao evento. O evento agora tem uma carga completa e está pronto para o consumo.
  5. O evento é entregue aos destinos síncronos, se houver.
  6. Caso exista algum destino assíncrono, o evento é armazenado em buffer para processamento posterior.
  7. O controle é devolvido ao código que contém o evento, e o processamento continua.

sqlfig04.gif

Figura 4 A vida de um evento do Extended Events (clique na imagem para ampliá-la)

Como mencionei anteriormente, deve-se tomar cuidado ao criar uma sessão de eventos, para que as ações síncronas ou o armazenamento em buffer dos destinos assíncronos não afetem o desempenho do código sob monitoramento.

Usando o Extended Events

Os Manuais Online do SQL Server 2008 contêm dois exemplos de uso do Extended Events: "Como determinar quais consultas estão mantendo bloqueios" e "Como localizar os objetos que detêm a maioria dos bloqueios."

Eu gostaria de percorrer um exemplo de configuração de uma sessão do Extended Events e analisar os resultados. Aprendi, quando comecei a usar o Extended Events no final de 2007, que montar uma sessão simples é muito fácil (usando as descomplicadas instruções DDL do T-SQL), mas analisar os resultados não é tão simples.

Os resultados são apresentados em XML, o que inicialmente me surpreendeu, até que eu percebesse que o imenso número de combinações possíveis de eventos e ações que podia ser coletado em uma sessão simples significava que não havia outro modo viável de armazenar um esquema extensível como esse.

Eu fui, durante muitos anos, desenvolvedor na equipe do mecanismo de armazenamento do SQL Server e me considero um programador altamente eficiente em C, C++ e assembly, mas precisei usar algumas horas tentando descobrir o código necessário para extrair dos dados XML, programaticamente, os campos de carga do evento. Não estou tentando dissuadir você de usar o Extended Events; pelo contrário, estou apenas avisando que, caso não esteja habituado a trabalhar com dados XML, é bom preparar-se para uma pequena curva de aprendizagem antes de poder ver resultados.

Veja a minha situação: sou administrador de banco de dados e uso o recurso Resource Governor do SQL Server 2008 para isolar vários grupos de minha empresa em um dos servidores de produção. Criei dois pools de recursos Resource Governor — Desenvolvimento e Marketing — para representar cada equipe que usa esse servidor. O Resource Governor permite que eu limite, para cada pool, o uso de CPU e de memória para execução de consultas, mas não o volume de recursos de E/S que eles usam. Assim, eu gostaria de instituir um mecanismo de cobrança retroativa que me ajudasse a amortizar o custo da atualização para uma nova SAN (rede de área de armazenamento) cobrando de cada equipe o uso de E/S naquele servidor.

Presumo que o modo mais fácil de disparar a captura das informações de E/S seja no momento em que se conclui qualquer instrução T-SQL e sei que no pacote package0 existe um evento chamado sql_statement_completed. Então, que dados são coletados na carga do evento?

A execução do código a seguir fornecerá a lista de todos os dados, inclusive as leituras (reads) e gravações (writes):

SELECT [name] FROM sys.dm_xe_object_columns
  WHERE [object_name] = 'sql_statement_completed';
GO

Não acho que essas sejam leituras e gravações físicas (quando os dados são lidos ou gravados no disco, e não apenas na memória do pool de buffers), mas darão uma idéia da proporção de recursos de E/S usados por cada equipe.

Agora preciso descobrir qual equipe executa uma instrução T-SQL específica e, para isso, preciso de uma ação que me informe. A execução do código a seguir fornece uma lista de todas as ações que posso executar quando um evento é disparado, inclusive uma que coleta a session_resource_pool_id no pacote sqlserver:

SELECT xp.[name], xo.*
FROM sys.dm_xe_objects xo, sys.dm_xe_packages xp
WHERE xp.[guid] = xo.[package_guid]
   AND xo.[object_type] = 'action'
ORDER BY xp.[name];

Posso obter a lista de pools de recursos que defini para o Resource Governor e correlacioná-la com as IDs coletadas pela sessão do Extended Events. Agora estou pronto para definir minha sessão. Observe que, quando executo este código, ele primeiro verifica se existe uma sessão de eventos com o mesmo nome. Caso encontre uma com o mesmo nome, ele descarta a sessão. Este é o código:

IF EXISTS (
SELECT * FROM sys.server_event_sessions
    WHERE name = 'MonitorIO')
DROP EVENT SESSION MonitorIO ON SERVER;
GO

CREATE EVENT SESSION MonitorIO ON SERVER
ADD EVENT sqlserver.sql_statement_completed
  (ACTION (sqlserver.session_resource_pool_id))
ADD TARGET package0.ring_buffer;
GO

Ele então cria uma nova sessão com um único evento, sql_statement_completed, que também executa a ação session_resource_pool_id, registrando tudo em um buffer em anel enquanto eu ainda estou criando um protótipo. (Na produção, é mais provável que eu opte por um destino de arquivo assíncrono.)

Para iniciar minha sessão, precisarei executar este código:

ALTER EVENT SESSION MonitorIO ON SERVER
STATE = START;
GO

Agora ele está em funcionamento.

Depois de simular alguma atividade das equipes de marketing e desenvolvimento, estou pronto para analisar os resultados da sessão. Este código extrairá os dados do buffer em anel:

SELECT CAST(xest.target_data AS XML) StatementData
  FROM sys.dm_xe_session_targets xest
JOIN sys.dm_xe_sessions xes ON
  xes.address = xest.event_session_address
WHERE xest.target_name = 'ring_buffer'
  AND xes.name = 'MonitorIO';
GO

No entanto, ele extrai os dados como um grande valor XML. Se eu quiser dividi-lo ainda mais, poderei usar o código mostrado na Figura 5.

Figura 5 Dividindo os dados XML

SELECT
  Data2.Results.value ('(data/.)[6]', 'bigint') AS Reads,
  Data2.Results.value ('(data/.)[7]', 'bigint') AS Writes,
  Data2.Results.value ('(action/.)[1]', 'int') AS ResourcePoolID
FROM
(SELECT CAST(xest.target_data AS XML) StatementData
  FROM sys.dm_xe_session_targets xest
  JOIN sys.dm_xe_sessions xes ON
    xes.address = xest.event_session_address
  WHERE xest.target_name = 'ring_buffer'
    AND xes.name = 'MonitorIO') Statements
CROSS APPLY StatementData.nodes ('//RingBufferTarget/event') AS Data2 (Results);
GO

Isso funciona, mas fornece uma linha de saída para cada evento capturado. Esse não é um ótimo formato, e tem mais: eu gostaria de obter saída agregada, de modo que decidi usar uma tabela derivada, como se pode ver na Figura 6.

Figura 6 Obtendo saída agregada

SELECT DT.ResourcePoolID,
  SUM (DT.Reads) as TotalReads,
  SUM (DT.Writes) AS TotalWrites
FROM
(SELECT 
  Data2.Results.value ('(data/.)[6]', 'bigint') AS Reads,
  Data2.Results.value ('(data/.)[7]', 'bigint') AS Writes,
  Data2.Results.value ('(action/.)[1]', 'int') AS ResourcePoolID
FROM
(SELECT CAST(xest.target_data AS XML) StatementData
  FROM sys.dm_xe_session_targets xest
  JOIN sys.dm_xe_sessions xes ON
    xes.address = xest.event_session_address
  WHERE xest.target_name = 'ring_buffer'
    AND xes.name = 'MonitorIO') Statements
CROSS APPLY StatementData.nodes ('//RingBufferTarget/event') AS Data2 (Results)) AS DT
WHERE DT.ResourcePoolID > 255 –- only show user-defined resource pools
GROUP BY DT.ResourcePoolID;
GO

Ufa! Sem dúvida, há algumas instruções complicadas aí, mas funcionam bem. Agora eu consegui o resultado que queria. Veja a saída dessa consulta sobre os dados de meu teste, mostrada na Figura 7.

Figura 7 Saída da minha consulta
ResourcePoolID TotalReads TotalWrites
256 3831 244
257 5708155 1818

Eu sei que o pool de recursos 256 é do marketing e que o 257 é do desenvolvimento — assim, esses números fazem sentido quanto à atividade de banco de dados que eu esperava das equipes da empresa. Eu não poderia produzir esse resultado tão facilmente se não tivesse usado o Extended Events.

E, para terminar, eu preciso encerrar a sessão usando o seguinte código:

ALTER EVENT SESSION MonitorIO ON SERVER
STATE = STOP;
GO

Para ver mais sobre o que estou falando em termos de saída de cada estágio deste exemplo, assista ao screencast que acompanha este artigo. Você o encontrará em technetmagazine.com/video.

A sessão system_health do Extended Events

O SQL Server 2008 é fornecido com uma sessão predefinida para ser executada por padrão e é chamada de sessão system_health. Essa sessão foi idéia da equipe de suporte ao produto e controla as informações que a equipe normalmente usa para depurar sistemas de clientes, como quando ocorre um deadlock ou um erro muito grave. A sessão é criada e iniciada como parte do processo de instalação de uma instância do SQL Server 2008 e controla eventos em um buffer em anel para que ela não consuma memória em excesso.

Para ver o que o buffer em anel contém, use o seguinte código:

SELECT CAST (xest.target_data AS XML)
FROM sys.dm_xe_session_targets xest 
JOIN sys.dm_xe_sessions xes ON
xes.address = xest.event_session_address 
WHERE xes.name = 'system_health';
GO

O blog de suporte ao SQL no Microsoft PSS tem informações mais detalhadas sobre o que é controlado por essa sessão.

Conclusão

Eu soube que a equipe do SQL Server está planejando adicionar futuramente muitos outros eventos ao sqlserver.exe. Na verdade, o número saltou de 165 na versão CTP (Community Technology Preview) de fevereiro de 2007 para 254 na versão RTM (versão para produção).

Há alguns eventos que também parecem realmente interessantes para investigar, como os de captura de dados de alteração (que abordei em meu artigo "Controlando alterações no seu banco de dados empresarial" na edição de novembro de 2008 da TechNet Magazine), compactação de dados e divisão de páginas de índice. A divisão de páginas de índice parece um modo promissor de descobrir quais índices estão criando a fragmentação que consome o desempenho sem a necessidade de executar periodicamente a DMV sys.dm_db_index_physical_stats em todos os índices.

De modo geral, o novo sistema Extended Events permite um monitoramento bem sofisticado, que nunca tinha sido possível antes. Embora ele exija um pouco de estudo para descobrir qual análise de XML você precisará fazer para chegar aos dados, as vantagens do novo sistema superam em muito o aborrecimento de aprender alguns novos conceitos de codificação.

Espero que este artigo tenha dado a você uma visão geral do Extended Events suficiente para interessá-lo e tenha mostrado o tipo de coisas que você pode fazer com ele. Feliz solução de problemas! Como sempre, se tiver algum comentário ou dúvida, sinta-se à vontade para me escrever: Paul@SQLskills.com.

Paul S. Randal é diretor administrativo da SQLskills.com e MVP do SQL Server. Ele trabalhou na equipe do mecanismo de armazenamento do SQL Server da Microsoft de 1999 a 2007. Paul escreveu o DBCC CHECKDB/repair para o SQL Server 2005 e foi responsável pelo mecanismo de armazenamento principal durante o desenvolvimento do SQL Server 2008. Paul é especialista em recuperação de desastres, alta disponibilidade e manutenção de banco de dados, e participa regularmente em conferências pelo mundo. Ele bloga em SQLskills.com/blogs/paul.