Hey guys!
Nesse post de hoje, gostaria de compartilhar uma solução que criei para responder uma dúvida em um dos grupos do Telegram em que participo, que foi a pergunta de como saber há quanto tempo um database está online no SQL Server. Isso não é há quanto tempo a instância está online e sim há quanto tempo um database está online.
Para resolver essa dúvida, pensei em utilizar o próprio log do SQL Server para identificar quando cada database foi iniciado e retornar para o usuário. A query abaixo irá retornar todos os bancos que estão no último arquivo de log, junto com a data da última vez que o banco foi inicializado e o tempo decorrido desde então até a hora atual.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
IF (OBJECT_ID('tempdb..#StartupDB') IS NOT NULL) DROP TABLE #StartupDB CREATE TABLE #StartupDB ( [LogNumber] TINYINT, [LogDate] DATETIME, [ProcessInfo] NVARCHAR(50) COLLATE SQL_Latin1_General_CP1_CI_AI, [Text] NVARCHAR(MAX) COLLATE SQL_Latin1_General_CP1_CI_AI, [Database] AS (REPLACE(REPLACE(SUBSTRING([Text], CHARINDEX('''', [Text]), 128), '''', ''), '.', '')) ) INSERT INTO #StartupDB (LogDate, ProcessInfo, [Text]) EXEC master.dbo.sp_readerrorlog 0, 1, N'Starting up database ', NULL SELECT [Database], MAX(LogDate) AS LogDate, (CASE WHEN DATEDIFF(SECOND, MAX(LogDate), GETDATE()) > 86400 THEN CAST(DATEDIFF(SECOND, MAX(LogDate), GETDATE()) / 86400 AS VARCHAR) + 'd ' ELSE '' END) + RIGHT('00' + CAST((DATEDIFF(SECOND, MAX(LogDate), GETDATE()) / 3600) % 24 AS VARCHAR), 2) + ':' + RIGHT('00' + CAST((DATEDIFF(SECOND, MAX(LogDate), GETDATE()) / 60) % 60 AS VARCHAR), 2) + ':' + RIGHT('00' + CAST(DATEDIFF(SECOND, MAX(LogDate), GETDATE()) % 60 AS VARCHAR), 2) + '.' + RIGHT('000' + CAST(DATEDIFF(SECOND, MAX(LogDate), GETDATE()) AS VARCHAR), 3) AS TimeRunning FROM #StartupDB GROUP BY [Database] ORDER BY 1 |
Caso você queira analisar todo o histórico de inicialização dos databases, varrendo por todos os arquivos de logs (não somente o último):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
IF (OBJECT_ID('tempdb..#Arquivos_Log') IS NOT NULL) DROP TABLE #Arquivos_Log CREATE TABLE #Arquivos_Log ( [idLog] INT, [dtLog] NVARCHAR(30) COLLATE SQL_Latin1_General_CP1_CI_AI, [tamanhoLog] INT ) IF (OBJECT_ID('tempdb..#StartupDB') IS NOT NULL) DROP TABLE #StartupDB CREATE TABLE #StartupDB ( [LogNumber] TINYINT, [LogDate] DATETIME, [ProcessInfo] NVARCHAR(50) COLLATE SQL_Latin1_General_CP1_CI_AI, [Text] NVARCHAR(MAX) COLLATE SQL_Latin1_General_CP1_CI_AI, [Database] AS (REPLACE(REPLACE(SUBSTRING([Text], CHARINDEX('''', [Text]), 128), '''', ''), '.', '')) ) INSERT INTO #Arquivos_Log EXEC sys.sp_enumerrorlogs DECLARE @Contador INT = 0, @Total INT = (SELECT COUNT(*) FROM #Arquivos_Log) WHILE(@Contador < @Total) BEGIN INSERT INTO #StartupDB (LogDate, ProcessInfo, [Text]) EXEC master.dbo.xp_readerrorlog @Contador, 1, N'Starting up database ', NULL, NULL, NULL -- Update log file number UPDATE #StartupDB SET LogNumber = @Contador WHERE LogNumber IS NULL SET @Contador += 1 END SELECT * FROM #StartupDB ORDER BY LogDate DESC |
Nas duas soluções apresentadas, você pode usar a coluna de “Database” para filtrar os bancos selecionados e acredito que a dúvida original foi respondida por esses 2 scripts.
É isso aí, pessoal! Espero que tenham gostado dessa dica. Você conhece alguma outra solução para responder essa dúvida? Deixe aqui nos comentários 🙂
Um grande abraço e até a próxima!
Grande Dirceu, sensacional a solução.
Parabéns….