Banco de Dados

5 out, 2012

Consultando o Log de erro do SQL Server usando T-SQL

Publicidade

A leitura diária dos arquivos de log do SQL Server é uma das tarefas primárias do DBA. Particularmente, tenho o hábito de visualizar o log corrente a cada dez minutos (no máximo), pois, a leitura do log faz parte da minha estratégia de monitoração. Nesse sentido, tenho preferido consultar os log usando T-SQL, ao invés da interface gráfica (Log File Viewer). Dentre os principais motivos para preferir o T-SQL destaco:

  • A visualização fica mais fácil e o conteúdo do arquivo é carregado mais rapidamente (tente abrir um arquivo de log de erro muito grande usando o Log File Viewer e você sentirá uma certa demora);
  • Usando T-SQL é possível fazer pesquisas customizadas sobre o log do mesmo modo como fazemos na interface gráfica, contudo, a pesquisa com T-SQL é mais rápida;
  • E a principal vantagem, no meu ponto de vista, é que via T-SQL podemos ler o log de erro de vários servidores ao mesmo tempo, executando um único comando.

Para fazermos a leitura via T-SQL podemos utilizar as seguintes SP’s:

  • Sp_readerrorlog
  • Xp_readerrorlog

Os arquivos de Log

Os logs de erro do SQL Server são salvo em arquivos, por padrão, na subpasta “Log” da unidade de disco onde a instância foi instalada. É possível abrir e visualizar o conteúdo desses arquivos utilizando um editor de texto como o Notepad.

Toda vez que a instância é reiniciada, o arquivo corrente é arquivado e renomeado sob o nome ERRORLOG.1, enquanto um novo arquivo de log é criado com o nome ERRORLOG. Por default, o SQL Server mantém até seis arquivos de log arquivados. Caso queira aumentar esse limite, estando no SQL Server Management Studio, faça conforme ilustrado nas figuras abaixo:

O arquivo de log corrente tem índice zero e essa informação é importante para a utilização das SP’s de leitura do log de erro que falaremos mais adiante.

É possível listar via T-SQL os arquivos de log de erro da instância. Veja como:

exec sp_enumerrorlogs

Veja que a stored procedure listou os arquivos de log de erro. Neste caso, os seis logs arquivados e o log corrente (de índice zero). Também mostrou a data e hora da última entrada no log (último registro) e o tamanho em disco do arquivo.

Usando SP_READERRORLOG / XP_READERRORLOG

Em termos de sintaxe e de benefícios, ambas SP’s são idênticas. Contudo, é válido destacar que a XP_READERRORLOG é uma procedure estendida, além de não documentada.

Para visualizar o log de erros atual do SQL Server simplesmente execute:

exec sp_readerrorlog


Essa stored procedure tem os seguintes parâmetros opcionais:

Parâmetro Valores Descrição
P1 0,1,2,4,5,6… Indica o número do arquivo de log a ser lido. O default é 0.
P2 1 ou 2 Indica o tipo de log a ser lido, onde: 1 = sql server; 2 = sql agent. O default é 1, ou seja, o log do sql server
P3 Texto entre aspas simples ou aspas duplas a ser localizado dentro do log (coluna Text). ATENÇÃO: quando usar a XP_READERRORLOG o texto deve estar entre aspas duplas. A pesquisa é parcial, procurando em qualquer parte da palavra. Deixe NULL neste parâmetro para não utilizá-lo ou simplesmente basta omiti-lo.
P4 Trata-se de uma segunda string a ser pesquisada, objetivando refinar a consulta. Na verdade este parâmetro produz a combinação P3 + P4, ou seja, as duas palavras pesquisadas devem existir na mesma entrada (linha) do log. Deixe NULL neste parâmetro para não utilizá-lo ou simplesmente basta omiti-lo.

Vejamos alguns exemplos:

Localizar as entradas que contenham a palavra AdventureWorks no log corrente do SQL Server:

exec sp_readerrorlog 0, 1, 'adventureworks'
 

Localizar as entradas que contenham as palavras CHECKDB e AdventureWorks no log corrente do SQL Server:

exec sp_readerrorlog 0, 1, 'checkdb', 'adventureworks'

Esse tipo de consulta no log é muito útil quando queremos pesquisar por erros ou, por exemplo, filtrar as entradas referentes a backup, etc.

Criando um script para consultas mais refinadas

Como comentei no início do artigo, tenho o hábito de ficar lendo o log em intervalos de no máximo dez minutos. Desta forma, não tenho a necessidade de listar o log por completo, apenas as informações dos últimos dez minutos e, caso se faça necessário, ir ampliando esse range. Fazer esse tipo de pesquisa usando a SP_READERRORLOG ou XP_REAERRORLOG não é possível. Por conta disso, estou deixando o script de uma stored procedure “personalizada”, que possibilita a realização de consultas bem flexíveis. Recomendo criar essa SP na database Master ou em um banco de dados criado para fins administrativos. Caso prefira, você pode baixar o script com o código fonte da SP aqui.

USE Master
GO

IF OBJECT_ID('dbo.uspErrorLog') IS NOT NULL
DROP PROCEDURE dbo.uspErrorLog;
GO

CREATE PROCEDURE dbo.uspErrorLog
(
-- Quantidade de minutos a retroagir na pesquisa.
-- O Default são 30 minutos
-- Informe NULL para desconsiderar e não usar este parâmetro
@MinutosRetroagir INT = 30,

-- Data inicial para a pesquisa no log.
-- Registros com datas menores serão desconsiderados
-- O Default é NULL
-- Informe NULL para desconsiderar e não usar este parâmetro
@DataInicial DATETIME = NULL,

-- Data final para a pesquisa no log.
-- Registros com datas maiores serão desconsiderados
-- O Default é NULL
-- Informe NULL para desconsiderar e não usar este parâmetro
@DataFinal DATETIME = NULL,

-- Texto a ser pesquisado dentro da coluna ProcessInfo do log
-- Exemplo: Server, Backup, SPID, etc.
-- A pesquisa pelo texto é parcial (em qualquer parte)
-- O Default é NULL
-- Informe NULL para desconsiderar e não usar este parâmetro
@Processo VARCHAR(50) = NULL,

-- Texto a ser pesquisado dentro da coluna Text do log
-- Exemplo: error, starting, etc.
-- A pesquisa pelo texto é parcial (em qualquer parte)
-- O Default é NULL
-- Informe NULL para desconsiderar e não usar este parâmetro
@Texto VARCHAR(100) = NULL,

-- Filtra a pesquisa para exibir apenas o log do nome do servidor informado
-- Use este parâmetro quando estiver pesquisando o log de vários servidores ao mesmo tempo
-- O Default é NULL
-- Informe NULL para desconsiderar e não usar este parâmetro
@NomeServidor VARCHAR(128) = NULL
)
AS

DECLARE @Tmp TABLE
(    ID INT IDENTITY,
Data DATETIME,
Processo VARCHAR(50),
Texto VARCHAR(4000)
);
INSERT INTO @Tmp (Data, Processo, Texto) exec sp_readerrorlog;

SELECT * FROM @Tmp t
WHERE t.Data >=
CASE WHEN @MinutosRetroagir IS NOT NULL THEN DATEADD(MINUTE, -@MinutosRetroagir, GETDATE())
ELSE t.Data END

AND t.Data >= ISNULL(@DataInicial, t.Data)

AND t.Data <= ISNULL(@DataFinal, t.Data)

AND t.Processo LIKE
CASE WHEN @Processo IS NOT NULL THEN '%' + @Processo + '%'
ELSE t.Processo END

AND t.Texto LIKE
CASE WHEN @Texto IS NOT NULL THEN '%' + @Texto + '%'
ELSE t.Texto END

AND SERVERPROPERTY('ServerName') =
ISNULL(@NomeServidor, CONVERT(VARCHAR(128), SERVERPROPERTY('ServerName')))

ORDER BY t.ID DESC;

GO

Reciclando o log de erro

Como já foi mencionado, o log de erro é reciclado (reiniciado) automaticamente toda vez que a instância sofre um restart. Considerando que um servidor de banco não é resetado com frequência – normalmente permanece vários meses online, a tendência é o log ficar demasiado grande, dificultando a análise e leitura. Assim, quero deixar uma sugestão: recicle manualmente, de tempos em tempos, o log de erro do SQL Server. Particularmente, faço essa reciclagem a cada sete dias – normalmente crio um job que é executado aos domingos. Contudo, essa frequência de reciclagem varia de ambiente para ambiente, além de preferências e políticas.

O comando para reciclar manualmente o log de erros é o seguinte:

DBCC ERRORLOG

Conclusão

Inclua em sua estratégia diária de monitoramento a leitura dos log’s de erro do SQL Server. Em ambientes com várias instâncias essa tarefa pode ser facilitada, e muito, através do T-SQL, permitindo analisar o log de várias instâncias ao mesmo.

Até o próximo artigo!