数据库恢复完成时间的历史?

Raz*_*anu 5 sql-server restore

我正在尝试估计 SQL 2012 上几个 1TB+ 数据库的还原时间。是否可以查看去年已完成的还原并列出完成时间?这是世界另一端的一个奇怪的远程服务器,我所知道的完全恢复用于在新的每个月初运行,出于某种原因,但无法弄清楚如何访问历史记录。

Aar*_*and 18

MSDB 中未跟踪此信息,因此无法在那里找到它(除非还原操作在作业中处于其自己的步骤中,在这种情况下,您可以从 中获取它msdb.dbo.sysjobhistory)。

如果您不能依赖作业历史记录,并且它足够新,您可以从默认跟踪中近似它,假设系统在还原完成后立即对数据库执行某些操作(这发生在我所有的测试,尽管可能存在这种情况不会发生的情况,例如使用 norecovery 恢复或恢复只读数据库 - 这两种情况我都没有测试):

DECLARE @path NVARCHAR(260);

SELECT 
   @path = REVERSE(SUBSTRING(REVERSE([path]), 
   CHARINDEX(CHAR(92), REVERSE([path])), 260)) + N'log.trc'
FROM    sys.traces
WHERE   is_default = 1;

SELECT *, rn = ROW_NUMBER() OVER 
  (PARTITION BY DatabaseName ORDER BY StartTime)
INTO #blat
FROM sys.fn_trace_gettable(@path, DEFAULT) 
WHERE DatabaseName IN (
  N'db1', N'db2' -- , ...
)
ORDER BY StartTime DESC; 

SELECT b.DatabaseName, b.TextData, 
  ApproximateRestoreTime = DATEDIFF(MILLISECOND, b.StartTime, b2.StartTime)
FROM #blat AS b 
LEFT OUTER JOIN #blat AS b2
ON b.DatabaseName = b2.DatabaseName
AND b2.rn = b.rn + 1
WHERE b.EventClass = 115 AND b.EventSubClass = 2
ORDER BY b.StartTime DESC;

GO
DROP TABLE #blat;
Run Code Online (Sandbox Code Playgroud)

(我尝试了这个 Stack Overflow 答案中的查询,但它们的效率并不高 - 非常欢迎您也尝试这些查询,看看它们是否更适合您的需求。)

我测试过这种策略不起作用的一个场景是,如果所有自动统计选项都被禁用 - 因为在恢复后似乎立即发生的活动是对系统表的一些自动统计操作,如syscolparssysschobjs。这不会发生 - 即使对于系统表 - 当自动统计被禁用时。

如果您在还原后立即获得来自后续系统事件的时间戳,您将粗略估计还原所用的时间,但不一定非常精确。当然,您不会获得此类更精确的信息,如果您以交互方式运行还原,这些信息将输出到消息选项卡(并且它也会写入错误日志,只要未启用跟踪标志 3226 ):

RESTORE DATABASE 在 0.021 秒(108.258 MB/秒)内成功处理了 291 页。

但是您仍然可以从错误日志中提取此信息(同样,只要它最近发生并且没有过时)。如果您没有启用跟踪标志 3226,您应该使用以下查询在当前错误日志中看到与上述类似的所有消息:

EXEC sp_readerrorlog 0, 1, N'Restore', N'MB/sec';
Run Code Online (Sandbox Code Playgroud)

现在,一旦您确定了您所追求的时间范围,您就需要扩展您的搜索集,因为上面的消息没有包含数据库名称。因此,您可以从日志中追踪三组消息:数据库被标记为正在恢复的时间、恢复完成的时间以及包含页面和时间的消息(注意后者可能与如果您试图获得亚秒级粒度,则前两个)。

CREATE TABLE #x(LogDate DATETIME, p SYSNAME, [Text] NVARCHAR(MAX));
INSERT #x EXEC sp_readerrorlog 0, 1, N'Restore', N'MB/sec';
-- repeat for 1, 2, 3, 4, 5, 6 if you want to capture more history:
--INSERT #x EXEC sp_readerrorlog 1, 1, N'Restore', N'MB/sec';
--INSERT #x EXEC sp_readerrorlog 2, 1, N'Restore', N'MB/sec';
--...

CREATE TABLE #y(LogDate DATETIME, p SYSNAME, [Text] NVARCHAR(MAX));
INSERT #y EXEC sp_readerrorlog 0, 1, N'is marked RESTORING';
-- again repeat for 1, 2, 3, 4, 5, 6 like above

CREATE TABLE #z(LogDate DATETIME, p SYSNAME, [Text] NVARCHAR(MAX));
INSERT #z EXEC sp_readerrorlog 0, 1, N'Restore is complete';
-- one more time, you may need to repeat if you want more history

SELECT LogDate, [Text]
FROM 
(
  SELECT LogDate, [Text] FROM #x
  UNION ALL SELECT LogDate, [Text] FROM #y
  UNION ALL SELECT LogDate, [Text] FROM #z
) AS xyz
ORDER BY LogDate;

GO
DROP TABLE #x, #y, #z;
Run Code Online (Sandbox Code Playgroud)

如果您只使用单个数据库或数据库名称模式,则可以向第二个和第三个查询添加第二个过滤器,例如:

INSERT #y EXEC sp_readerrorlog 0, 1, N'is marked RESTORING', N'database_name';
Run Code Online (Sandbox Code Playgroud)

如果启用了跟踪标志 3226,您将只会收到前两条消息,而不会收到第三条消息。

如果您想解决恢复速度慢的问题,首先要确保启用了即时文件初始化(请参阅此处此处),并且您还可以主动监视该过程(除了该STATS选项,该选项不考虑撤消/重做、VLF 工作或 MSDB/历史维护)通过启用跟踪标志 3604/3605、3004 和 3014。有关详细信息,请参阅此文章