Consulta que muestra información de respaldo (exitosa y fallida) SQL Server

9

Tengo dos trabajos que respaldan dos bases de datos diferentes.
El trabajo 1 hace una copia de seguridad de DB1 El
trabajo 2 hace una copia de seguridad de DB2

DB1 no se puede hacer una copia de seguridad debido a la falta de espacio en la Unidad 1 que resulta en una falla del Trabajo 1. Para solucionar ese problema, solo tenía que agregar espacio. No es problema. Me dijeron sobre esto hoy cuando el problema ha estado ocurriendo durante un mes. Sí, sé que es una locura, pero es dev


Quiero obtener un historial de copia de seguridad completo para DB1. Sé que puedo recuperar información de copia de seguridad exitosa de la tabla msdb.dbo.backupset, pero quiero saber si hay una consulta que muestre copias de seguridad fallidas para una base de datos.

Mi consulta a continuación muestra el historial de copias de seguridad de una base de datos particular del 31/12/13 al 27/14/14. La información incluye el servidor, el nombre de la base de datos, las horas de inicio y finalización de la copia de seguridad, el tiempo total que tardó la copia de seguridad de la base de datos, el tamaño de la base de datos y el nombre del conjunto de copia de seguridad.

SELECT  
   distinct CONVERT(CHAR(100), SERVERPROPERTY('Servername')) AS Server, 
   msdb.dbo.backupset.database_name,  
   msdb.dbo.backupset.backup_start_date,  
   msdb.dbo.backupset.backup_finish_date, 
 CAST((DATEDIFF(second,  msdb.dbo.backupset.backup_start_date,msdb.dbo.backupset.backup_finish_date)) AS varchar)+ ' secs  ' AS [Total Time] ,

   Cast(msdb.dbo.backupset.backup_size/1024/1024 AS numeric(10,2)) AS 'Backup Size(MB)',   
   msdb.dbo.backupset.name AS backupset_name
FROM   msdb.dbo.backupmediafamily  
   INNER JOIN msdb.dbo.backupset ON msdb.dbo.backupmediafamily.media_set_id = msdb.dbo.backupset.media_set_id   
--Enter your database below
--and database_name = 'db_name_here'
and msdb.dbo.backupset.backup_start_date>'2013-12-31' and msdb.dbo.backupset.backup_start_date<'2014-01-27 23:59:59'
ORDER BY  
   msdb.dbo.backupset.database_name, 
   msdb.dbo.backupset.backup_start_date

¿Hay alguna forma de obtener esa información modificando mi código? Puedo recuperar el historial de JOB1 ejecutando una instrucción sql que se ejecuta contra la tabla sysjobhistory y sysjob. Esto puede ser una posibilidad remota. ¿Hay alguna manera de utilizar las tablas sysjobhistory, sysjob, backupset y backupsetmediafamily en msdb para producir los resultados que deseo?

iamZel
fuente

Respuestas:

15

Lamentablemente, backupsetno contiene copias de seguridad fallidas, y no sé de ningún otro lugar en el que se msdbpuedan almacenar, a menos que pueda confiar sysjobhistory, que no contiene todo el tiempo (dependiendo de su configuración de retención) y que ignoraría cualquier los intentos de respaldo que se realizaron fuera del contexto de un trabajo y que, en el caso de un trabajo que respalda muchas bases de datos, no proporcionarían diferenciación sobre qué base de datos realmente falló, a menos que sucediera al principio del trabajo, esto es porque el mensaje es bastante detallado pero se trunca.

Si sabe absolutamente que Job nsolo realiza una copia de seguridad de la base de datos y que cada falla de ese trabajo significa que la base de datos no fue respaldada (ya que el trabajo también podría fallar después de que la copia de seguridad se realizó correctamente, por ejemplo, tratando de reducir o realizar otro mantenimiento), entonces podría usar una consulta como esta:

DECLARE @job sysname, @db sysname;

SELECT @job = N'Job 1', @db = N'db_name';

SELECT  
   bs.database_name,  
   bs.backup_start_date,  
   bs.backup_finish_date, 
   [Total Time] = CAST((DATEDIFF(SECOND, bs.backup_start_date,bs.backup_finish_date))
     AS varchar(30))+ ' secs',
   CAST(bs.backup_size/1024/1024 AS decimal(10,2)) AS 'Backup Size(MB)',   
   h.[message]
FROM msdb.dbo.sysjobhistory AS h
INNER JOIN msdb.dbo.sysjobs AS j
ON h.job_id = j.job_id
AND h.step_id = 0
LEFT OUTER JOIN msdb.dbo.backupset AS bs
ON bs.database_name = @db
AND 
 ABS(DATEDIFF(SECOND, bs.backup_start_date, CONVERT(DATETIME,convert(char(8),h.run_date) 
   + ' ' + STUFF(STUFF(RIGHT('0'+CONVERT(char(6),h.run_time),6),3,0,':'),6,0,':')))) < 5
WHERE j.name = @job
ORDER BY bs.backup_start_date;

Sí, es realmente feo, porque sysjobhistoryaún, en SQL Server 2014 incluso, se almacena run_datey run_timecomo enteros separados. Apuesto a que quien tomó esa decisión todavía está en el fondo de los tableros de dardos en todo el edificio 35. También supone que la copia de seguridad es el primer paso en el trabajo, por lo tanto, la comparación de fecha / hora es menos que científica para asegurarse de que hayamos realizado correctamente correlacionó la instancia correcta del trabajo con la instancia correcta de la copia de seguridad. Oh, cómo desearía poder rediseñar el esquema para copias de seguridad y trabajos.

Si desea un alcance más amplio fuera del trabajo, puede buscar copias de seguridad fallidas en el registro de errores de SQL Server (si no se han eliminado):

EXEC sp_readerrorlog 0, 1, 'BACKUP failed'; -- current
EXEC sp_readerrorlog 1, 1, 'BACKUP failed'; -- .1 (previous)
EXEC sp_readerrorlog 2, 1, 'BACKUP failed'; -- .2 (the one before that)
....

(Pero no conozco una manera agradable y fácil de incorporar esa salida en su consulta existente).

También puede correlacionar las copias de seguridad exitosas "perdidas" de la traza predeterminada, p. Ej.

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 dt.DatabaseName, dt.StartTime, bs.backup_start_date, bs.backup_finish_date, 
  [Status] = CASE WHEN bs.backup_start_date IS NULL 
    THEN 'Probably failed'
    ELSE 'Seems like success'
  END
FROM sys.fn_trace_gettable(@path, DEFAULT) AS dt
LEFT OUTER JOIN msdb.dbo.backupset AS bs
ON dt.DatabaseName = bs.database_name
AND ABS(DATEDIFF(SECOND, dt.StartTime, bs.backup_start_date)) < 5
WHERE dt.EventClass = 115 -- backup/restore events
AND UPPER(CONVERT(nvarchar(max),dt.TextData)) LIKE N'BACKUP%DATABASE%'
--AND dt.DatabaseName = N'db_name' -- to filter to a single database
--AND bs.database_name = N'db_name'
ORDER BY dt.StartTime;

Por supuesto, esto también se basa en los datos del ciclo de rastreo predeterminado, el nombre de la base de datos no ha cambiado, etc. Y desafortunadamente, el rastreo predeterminado no diferencia entre copias de seguridad exitosas y fallidas, y el tiempo de inicio no coincidirá con precisión con el MSDB datos, pero siempre que no esté ejecutando copias de seguridad en un bucle, esto debería estar bien para observar. Intenté incorporar estos problemas en la consulta.

Finalmente, es posible que desee usar un FULL OUTER JOINallí, en caso de que el conjunto de copia de seguridad tenga un historial más largo que el rastreo predeterminado. Esto cambia la semántica de [Status]ligeramente.

También es posible que desee probar esta cosa desagradable , aunque no tuve mucha suerte con eso. Solo pude ver el estado actual o más reciente, por lo que solo ayudó cuando el trabajo falló la última vez que se ejecutó y, al igual que sysjobhistory, no pude obtener información sobre las copias de seguridad que se intentaron pero no a través de un trabajo.

Aaron Bertrand
fuente
Muchas gracias por la explicación detallada, pero recibo un error cuando ejecuto la primera consulta. Mensaje 139, Nivel 15, Estado 1, Línea 0 No se puede asignar un valor predeterminado a una variable local. Mensaje 137, Nivel 15, Estado 2, Línea 16 Debe declarar la variable escalar "@db"
iamZel
@iamZel, entonces estás en SQL Server 2005, no en SQL Server 2008.
Aaron Bertrand
Sí lo soy. Me olvidé de mencionar eso. Estoy en SQL2K5
iamZel
1
@iamZel La razón por la que pensé que estabas en SQL Server 2008 es porque etiquetaste tu pregunta con esa versión. Por favor, etiqueta con cuidado.
Aaron Bertrand
sp_readerrorlog es lo suficientemente bueno para mí. Muchas gracias Aaron
iamZel