- Get all the databases restoration information
- From all reporting, staging or testing environments
- Information about when the database restoration started and completed
- If the restoration is a full restore or differential
- When the backup file was ready
- Above said information is to be received through Email in a tabular format.
Below are the implementation steps.
- Write a SQL code to retrieve the complete information about backups. This includes when the backup file was ready, the restoration type, restoration start date time and end date time. Data restoration completed date time is unavailable in backup tables hence so get the information from the logs.
- Create a Power-Shell script to automate this process and fetch the data restoration information from across various reporting/staging/testing servers.
- Store this information in a table to maintain a history. This will help in analyzing if the restoration time is increasing/decreasing over a period of time.
- Fetch this information from the table and convert it into HTML tabular format. Send the information through Email using “db Mail“.
Here is my table which will hold the data restoration information.
CREATE TABLE dbo.RestoreInfo(
[Server] [NVARCHAR](30) NULL,
[Database] [NVARCHAR](100) NULL,
[RestoredBy] [NVARCHAR](100) NULL,
[RestoreType] [VARCHAR](15) NULL,
[backup_finish_date] [DATETIME] NULL,
[RestoreStarted] [DATETIME] NULL,
[RestoreFinished] [DATETIME] NOT NULL,
[RestoredFrom] [NVARCHAR](200) NULL,
[dtUpdTime] [DATETIME] DEFAULT CURRENT_TIMESTAMP
)
IF OBJECT_ID(‘tempdb.dbo.#RestoreInfo’, ‘U’) IS NOT NULL
DROP TABLE #RestoreInfo;
IF OBJECT_ID(‘tempdb.dbo.#TempLog’, ‘U’) IS NOT NULL
DROP TABLE #TempLog;
IF OBJECT_ID(‘tempdb.dbo.#DBRestoreTime’, ‘U’) IS NOT NULL
DROP TABLE #DBRestoreTime;
IF OBJECT_ID(‘tempdb.dbo.#FinalOutput’, ‘U’) IS NOT NULL
DROP TABLE #FinalOutput;
DECLARE @Getdate DATETIME, @EndDate DATETIME
IF DATEPART(WEEKDAY, GETDATE()) = 7
BEGIN
SET @Getdate = CONVERT(VARCHAR(10),GETDATE()-1,101)
SET @EndDate = DATEADD(HOUR,30,@Getdate)
–This is to run on Saturday to fetch Friday information.
–The restores whatever happens between Friday early hours to 30 hours
END
ELSE IF DATEPART(WEEKDAY, GETDATE()) = 1
BEGIN
SET @Getdate = CONVERT(VARCHAR(10),GETDATE()-1,101)
SET @EndDate = DATEADD(HOUR,33,@Getdate)
END
ELSE IF DATEPART(WEEKDAY, GETDATE()) IN(2,3,4,5)
BEGIN
SELECT @Getdate = CONVERT(VARCHAR(10),GETDATE(),101)
SELECT @EndDate = DATEADD(HOUR,9,@Getdate)
–9 is because to check if there is any restoration in last 9 hours
END
CREATE TABLE #TempLog
(
LogDate DATETIME ,
ProcessInfo NVARCHAR(50) ,
[Text] NVARCHAR(MAX)
)
CREATE TABLE #DBRestoreTime
(
ServerName VARCHAR(20),
LogDate DATETIME ,
ProcessInfo NVARCHAR(50) ,
[Text] NVARCHAR(MAX),
[RestoreText] NVARCHAR(MAX)
)
CREATE TABLE #FinalOutput(
[Server] [nvarchar](30) NULL,
[Database] [nvarchar](100) NULL,
[RestoredBy] [nvarchar](100) NULL,
[RestoreType] [varchar](15) NULL,
[backup_finish_date] [datetime] NULL,
[RestoreStarted] [datetime] NULL,
[RestoreFinished] [datetime] NOT NULL,
[RestoredFrom] [nvarchar](200) NULL,
[dtUpdTime] [datetime] NULL,
[MaxLogDate] [datetime] NULL
)
INSERT INTO dbo.RestoreInfo
SELECT
@@SERVERNAME,
rsh.destination_database_name,
rsh.user_name,
CASE WHEN rsh.restore_type = ‘D’ THEN ‘Database’
WHEN rsh.restore_type = ‘F’ THEN ‘File’
WHEN rsh.restore_type = ‘G’ THEN ‘Filegroup’
WHEN rsh.restore_type = ‘I’ THEN ‘Differential’
WHEN rsh.restore_type = ‘L’ THEN ‘Log’
WHEN rsh.restore_type = ‘V’ THEN ‘Verifyonly’
WHEN rsh.restore_type = ‘R’ THEN ‘Revert’
ELSE rsh.restore_type
END,
bs.backup_finish_date,
rsh.restore_date,
”,
bmf.physical_device_name,
GETDATE()
FROM msdb.dbo.restorehistory rsh
INNER JOIN msdb.dbo.backupset bs ON rsh.backup_set_id = bs.backup_set_id
INNER JOIN msdb.dbo.backupmediafamily bmf ON bmf.media_set_id = bs.media_set_id
WHERE rsh.restore_date BETWEEN @Getdate AND @EndDate
ORDER BY rsh.restore_date
— To retrieve restore time
INSERT INTO #TempLog
EXEC sp_readerrorlog
ALTER TABLE #TempLog ADD ServerName VARCHAR(20)
UPDATE #TempLog SET ServerName = @@SERVERNAME
DELETE FROM #TempLog WHERE LogDate NOT BETWEEN @Getdate AND @EndDate
DELETE FROM #TempLog WHERE
Text NOT LIKE ‘%Restore is complete on database%’ AND
Text NOT LIKE ‘%The database is now available%’ AND
— Text NOT LIKE ‘%restore database successfully processed%’ AND
Text NOT LIKE ‘%changes were restored%’ AND
Text NOT LIKE ‘%RESTORE DATABASE successfully%’ AND
Text NOT LIKE ‘%Database was restored%’
INSERT INTO #DBRestoreTime (
ServerName,
LogDate,
ProcessInfo,
[Text],
RestoreText )
SELECT ServerName,
LogDate,
ProcessInfo,
[Text],
LAG(Text)
OVER (ORDER BY LogDate)
FROM #TempLog a
INSERT INTO #FinalOutput
SELECT [Server],
[Database],
RestoredBy,
RestoreType,
backup_finish _date,
RestoreStarted,
RestoreFinished,
RestoredFrom,
dtUpdTime,
MAX(b.LogDate) MaxLogDate
FROM dbo.RestoreInfo a
JOIN #DBRestoreTime b ON a.Server = b.ServerName
AND RestoreText LIKE ‘%’+[Database]+’%’
WHERE RestoreStarted BETWEEN @Getdate AND @EndDate
GROUP BY [Server],
[Database],
RestoredBy,
RestoreType,
backup_finish_date,
RestoreStarted,
RestoreFinished,
RestoredFrom,
dtUpdTime
UPDATE a SET [RestoreFinished] = b.MaxLogDate FROM dbo.RestoreInfo a
JOIN #FinalOutput b ON a.Server = b.Server AND a.[Database] = b.[Database] AND
CONVERT(VARCHAR(10),a.RestoreStarted,101) = CONVERT(VARCHAR(10),b.RestoreStarted,101)
clear;
$Servers = Get-Content “D:\Monitoring_RestoreInfo\Computers.txt”;
foreach($computer in $Servers)
{ invoke-sqlcmd -inputfile “D:\Monitoring_RestoreInfo\Restore Information SQL Server.sql” -serverinstance $computer -database “msdb” -ErrorAction ‘Stop’ -Verbose -QueryTimeout 1800 # the parameter -database can be omitted based on what your sql script does.
}
Create a windows scheduled task in the server in where you have an access to other servers. The screenshots are given in the below slide show.
- Program/Script: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
- Add arguments (Optional): D:\Monitoring_RestoreInfo\DBRestoreInfo.ps1
- Start In : D:\Monitoring_RestoreInfo\
DECLARE @xml NVARCHAR(MAX)
DECLARE @body NVARCHAR(MAX)
SET @xml = CAST(( SELECT [Server] AS ‘td’,”,
[Database] AS ‘td’,”,
[RestoreType] AS ‘td’,”,
CONVERT(varchar(25), [backup_finish_date],21) AS ‘td’,”,
CONVERT(varchar(25), [RestoreStarted],21) AS ‘td’,”,
CONVERT(varchar(25), [RestoreFinished],21) AS ‘td’,”,
[RestoredFrom] AS ‘td’,”,
CONVERT(varchar(25), [dtUpdTime],21) AS ‘td’
FROM [dbTest].[dbo].[RestoreInfo] WITH (NOLOCK)
WHERE RestoreStarted >= DATEADD(HOUR,-24, GETDATE())
ORDER BY [Server]
FOR XML PATH(‘tr’), ELEMENTS ) AS NVARCHAR(MAX))
SET @Body = ‘<html><head>’
+ ‘<style>’
+ ‘th {border: solid black 1px;padding-left:5px;padding-right:5px;padding-top:1px;padding-bottom:1px;font-size:10pt;} ‘
+ ‘td {border: solid black 1px;padding-left:5px;padding-right:5px;padding-top:1px;padding-bottom:1px;font-size:10pt;} ‘
+ ‘</style>’
+ ‘</head>’
+ ‘<body>’
+ ‘<h4>Data Restoration Info</h4>’
+ ‘<table border=”1″>’
+ ‘<tr>’
+ ‘<th>Server</th>’
+ ‘<th>Database</th>’
+ ‘<th>RestoreType</th>’
+ ‘<th>BackupFinished</th>’
+ ‘<th>RestoreStarted</th>’
+ ‘<th>RestoreFinished</th>’
+ ‘<th>RestoredFrom</th>’
+ ‘<th>dtUpdTime</th>’
+ ‘</tr>’
SET @Body = @Body + @xml +'</table></body></html>’
EXEC msdb.dbo.sp_send_dbmail
@profile_name = ‘SQLProfile’, — replace with your SQL Database Mail Profile
@body = @body,
@body_format =’HTML’,
@from_address = ‘RestoreInfo <shaikshafi.nabi@gmail.com>’,
@recipients = ‘shaikshafi.nabi@gmail.com’, — replace with your email address
@subject = ‘Database Restoration Info’ ;
Thank you for visiting my blog. Please do let me know if you need more clarification in this implementation.
One comment