2010-09-23 8 views
7

Im cercando di scrivere una query che mi dirà quanto tempo un ripristino (completa o log) ha assunto SQL Server 2008.Come posso interrogare quanto tempo impiega un ripristino del database SQL?

posso eseguire la query per scoprire quanto tempo il backup ha avuto:

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 

Questa interrogazione mi dirà cosa viene ripristinato, ma ora quanto tempo c'è voluto:

select * from msdb..restorehistory 

restorehistory ha una colonna backup_set_id che collegherà a msdb..backupset, ma che mantengono la data di inizio e di fine del backup non il ripristino.

Qualche idea su dove interrogare l'ora di inizio e di fine per i ripristini?

risposta

12

trovare il tempo RESTORE DATABASE, ho scoperto che è possibile utilizzare questa query:

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; 

Il rovescio della medaglia è, si noterà che, almeno sul mio server di prova, il EndTime è sempre nullo .

Quindi, mi è venuta una seconda query per cercare di determinare l'ora di fine. Prima di tutto, mi scuso che questo è abbastanza brutto e nidificato come un matto.

La query di seguito assume il seguente:

  1. Quando un ripristino viene eseguito, per quella DatabaseID e ClientProcessID, il prossimo EventSequence contiene il TransactionID abbiamo bisogno.
  2. Vado quindi a cercare il massimo EventSequence per la transazione
  3. Infine, seleziono il record che contiene RESTORE DATABASE e la transazione massima associata a tale record.

Sono sicuro che qualcuno probabilmente può prendere quello che ho fatto e perfezionare, ma questo sembra lavorare sul mio ambiente di test:

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 

EDIT

ho fatto un po ' modifiche alla query, poiché uno dei database di test che ho usato è sensibile al maiuscolo/minuscolo e stava perdendo alcuni record. Ho anche notato durante il ripristino da disco che la DatabaseID è nullo, quindi sono la manipolazione che ora così:

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 
+0

È fantastico. Eseguirò questo al più presto sul mio server (s) – edosoft

+0

La prima query restituisce effettivamente l'ora di inizio dei ripristini, la seconda query non restituisce nulla, forse a causa di un join. Sto investigando ... – edosoft

+0

L'unica cosa che viene in mente è se gli ID del database non corrispondevano (perché erano nulli) - si spera che le mie modifiche funzionino per te. – LittleBobbyTables

5

Fai un lavoro. Quindi eseguirlo come lavoro. Quindi controlla Visualizza cronologia lavori. Quindi guarda la colonna della durata.

+0

Grazie. È davvero l'unico modo? Trovo difficile credere che il server SQL non memorizzi queste informazioni da qualche parte .. – edosoft

+0

Non l'unico modo; solo un modo semplice che consente anche di tenere traccia delle differenze nel tempo, poiché il sistema memorizza la cronologia del lavoro per un periodo di tempo. –

3

Mentre è in esecuzione è possibile verificare qualcosa di simile 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%' 

In alternativa è possibile utilizzare alcuni voodoo magia e interpretare il log delle transazioni nella seguente funzione di tabella, ma l'unica persona che conosco a comprendere qualsiasi informazione in questo registro è Paul Randal. So che a volte controlla l'errore del server, ma non so se si chiede StackOverflow.

select * from fn_dblog (NULL, NULL)

Spero che questo aiuti. Se riesci a usarlo e trova una soluzione, ti preghiamo di comunicarcelo.

Buona fortuna!