【问题标题】:How can I query how much time a SQL server database restore takes?如何查询 SQL Server 数据库还原需要多长时间?
【发布时间】:2010-09-23 08:59:52
【问题描述】:

我正在尝试编写一个查询,该查询将告诉我在 SQL Server 2008 上恢复(完整或日志)花费了多长时间。

我可以运行这个查询来了解备份花费了多少时间:

select  database_name, 
        [uncompressed_size] = backup_size/1024/1024,
        [compressed_size] = compressed_backup_size/1024/1024, 
        backup_start_date, 
        backup_finish_date, 
        datediff(s,backup_start_date,backup_finish_date) as [TimeTaken(s)], 
from    msdb..backupset b 
where   type = 'L' -- for log backups
order by b.backup_start_date desc

此查询将告诉我 什么 已恢复,但现在花了多少时间:

select * from msdb..restorehistory

restorehistory 有一个列backup_set_id 将链接到msdb..backupset,但它包含备份而不是恢复的开始和结束日期。

知道在哪里查询恢复的开始和结束时间吗?

【问题讨论】:

    标签: sql-server sql-server-2008 restore database-restore


    【解决方案1】:

    要查找 RESTORE DATABASE 时间,我发现可以使用这个查询:

    declare @filepath nvarchar(1000) 
    
    SELECT @filepath = cast(value as nvarchar(1000)) FROM [fn_trace_getinfo](NULL) 
    WHERE [property] = 2 and traceid=1 
    
    SELECT *
    FROM [fn_trace_gettable](@filepath, DEFAULT) 
    WHERE TextData LIKE 'RESTORE DATABASE%' 
    ORDER BY StartTime DESC; 
    

    缺点是,您会注意到,至少在我的测试服务器上,EndTime 始终为 NULL。

    所以,我想出了第二个查询来尝试确定结束时间。首先,我很抱歉这很丑陋,而且嵌套得像疯了一样。

    下面的查询假设如下:

    1. 运行恢复时,对于那个 DatabaseID 和 ClientProcessID,下一个 EventSequence 包含我们需要的 TransactionID。
    2. 然后我去找事务的最大 EventSequence
    3. 最后,我选择包含RESTORE DATABASE 的记录以及与该记录关联的最大事务。

    我确信有人可能会接受我所做的并对其进行改进,但这似乎适用于我的测试环境:

    declare @filepath nvarchar(1000) 
    
    SELECT @filepath = cast(value as nvarchar(1000)) FROM [fn_trace_getinfo](NULL) 
    WHERE [property] = 2 and traceid=1 
    
    SELECT *
    FROM [fn_trace_gettable](@filepath, DEFAULT) F5
    INNER JOIN 
    (
        SELECT F4.EventSequence MainSequence, 
             MAX(F3.EventSequence) MaxEventSequence, F3.TransactionID
        FROM [fn_trace_gettable](@filepath, DEFAULT) F3
        INNER JOIN 
        (
            SELECT F2.EventSequence, MIN(TransactionID) as TransactionID
            FROM [fn_trace_gettable](@filepath, DEFAULT) F1
            INNER JOIN 
            (
                SELECT DatabaseID, SPID, StartTime, ClientProcessID, EventSequence
                FROM [fn_trace_gettable](@filepath, DEFAULT)
                WHERE TextData LIKE 'RESTORE DATABASE%' 
            ) F2 ON F1.DatabaseID = F2.DatabaseID AND F1.SPID = F2.SPID 
                           AND F1.ClientProcessID = F2.ClientProcessID 
                           AND F1.StartTime > F2.StartTime
            GROUP BY F2.EventSequence
        ) F4 ON F3.TransactionID = F4.TransactionID 
        GROUP BY F3.TransactionID, F4.EventSequence
    ) F6 ON F5.EventSequence = F6.MainSequence 
        OR F5.EventSequence = F6.MaxEventSequence
    ORDER BY F5.StartTime
    

    编辑

    我对查询进行了一些更改,因为我使用的其中一个测试数据库区分大小写并且丢失了一些记录。从磁盘恢复时,我还注意到DatabaseID 为空,所以我现在也在处理它:

    SELECT * 
    FROM [fn_trace_gettable](@filepath, DEFAULT) F5 
    INNER JOIN  
    ( 
        SELECT F4.EventSequence MainSequence,  
             MAX(F3.EventSequence) MaxEventSequence, F3.TransactionID 
        FROM [fn_trace_gettable](@filepath, DEFAULT) F3 
        INNER JOIN  
        ( 
            SELECT F2.EventSequence, MIN(TransactionID) as TransactionID 
            FROM [fn_trace_gettable](@filepath, DEFAULT) F1 
            INNER JOIN  
            ( 
                SELECT DatabaseID, SPID, StartTime, ClientProcessID, EventSequence 
                FROM [fn_trace_gettable](@filepath, DEFAULT) 
                WHERE upper(convert(nvarchar(max), TextData)) 
                    LIKE 'RESTORE DATABASE%'  
            ) F2 ON (F1.DatabaseID = F2.DatabaseID OR F2.DatabaseID IS NULL) 
                       AND F1.SPID = F2.SPID  
                       AND F1.ClientProcessID = F2.ClientProcessID  
                       AND F1.StartTime > F2.StartTime 
            GROUP BY F2.EventSequence 
        ) F4 ON F3.TransactionID = F4.TransactionID  
        GROUP BY F3.TransactionID, F4.EventSequence 
    ) F6 ON F5.EventSequence = F6.MainSequence  
        OR F5.EventSequence = F6.MaxEventSequence 
    ORDER BY F5.StartTime 
    

    【讨论】:

    • 太棒了。我会尽快在我的服务器上运行这个
    • 第一个查询确实返回了恢复的开始时间,第二个查询没有返回任何内容,可能是由于连接。我正在调查...
    • 唯一想到的是数据库 ID 是否不匹配(因为它们为空)——希望我的编辑对你有用。
    • 再次感谢。编辑确实返回了行,我看到了恢复操作,但所有恢复的 endtime 都是 NULL。
    • @edosoft -- 正确;在我的测试期间,EndTime 始终为 NULL。为了弥补这一点,理想情况下,您应该在每次还原时获得两行,一根用于还原开始,另一行用于还原结束。第二个动作的 StartTime 实际上应该被认为是还原过程的结束时间。如果您不喜欢两行结果,应该可以接受我的查询并对其进行调整,使其仅返回一行,使用第一个事件的 StartTime 作为真正的 StartTime,并使用第二个事件的 StartTime作为别名的 EndTime,如果这有意义的话。
    【解决方案2】:

    让它成为一份工作。然后将其作为作业运行。然后检查查看作业历史。然后查看持续时间列。

    【讨论】:

    • 谢谢。这真的是唯一的方法吗?我很难相信 SQL Server 不会将这些信息存储在某个地方..
    • 不是唯一的方法;这只是一种简单的方法,还允许您跟踪一段时间内的差异,因为系统会将作业历史存储一段时间。
    【解决方案3】:

    在它运行时,您可以检查类似 dmv 的内容。

    select 
    d.name
    ,percent_complete
    ,dateadd(second,estimated_completion_time/1000, getdate())
    , Getdate() as now
    ,datediff(minute, start_time
    , getdate()) as running
    , estimated_completion_time/1000/60 as togo
    ,start_time
    , command 
    from sys.dm_exec_requests req
    inner join sys.sysdatabases d on d.dbid = req.database_id
    where 
    req.command LIKE '%RESTORE%'
    

    或者您可以使用一些魔法巫术并解释下表函数中的事务日志,但是我认识的唯一了解此日志中任何信息的人是 Paul Randal。 我知道他有时会检查服务器故障,但不知道他是否想知道 StackOverflow。

    从 fn_dblog(NULL,NULL) 中选择 *

    希望这会有所帮助。 如果您设法使用它并找到解决方案,请告诉我们。

    祝你好运!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-02-02
      • 1970-01-01
      • 1970-01-01
      • 2011-04-08
      • 2012-07-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多