Copias de seguridad de registro de transacciones de SQL Server: pruebe si el registro de cola sigue a la última copia de seguridad de registro conocida

11

Estamos usando SQL Server con modo de recuperación completa. Dada una copia de seguridad completa y una serie de copias de seguridad de registros, nos gustaría poder verificar si la cadena de registros está completa desde la última copia de seguridad completa hasta el registro de cola actual. (Sin realmente restaurar estas copias de seguridad; el propósito aquí es probar la consistencia de las copias de seguridad).

Ya sé cómo hacer esto para las copias de seguridad existentes: usando RESTORE HEADERONLY obtengo FirstLSN y LastLSN de cada archivo, que se pueden comparar para archivos consecutivos, para determinar si son compatibles.

Sin embargo, no sé cómo verificar si el registro de cola sigue a la última copia de seguridad del registro.

Si tuviera el FirstLSN del registro de cola, podría compararlo con el LastLSN de la última copia de seguridad del registro. Pero, ¿cómo puedo obtener el FirstLSN del registro de cola?

Necesito una solución que funcione desde SQL Server 2005 en adelante (idealmente usando t-sql). Hasta ahora, he buscado en Google en vano. Por cierto. Primero publiqué esto en stackoverflow; pero lo migró aquí porque se marcó fuera de tema allí.

EDITAR

Probé las dos soluciones proporcionadas en un pequeño ejemplo (SQL Server 2005, 9.0.5057):

BACKUP DATABASE TestDb TO DISK = 'C:\temp\backup test\Full.bak' 

-- fire some update queries

BACKUP LOG TestDb TO DISK =  'C:\temp\backup test\Log1.bak' 

-- fire both queries from the provided answers: 
-- Martin Smith's answer yields: 838886656088920652852608
-- Shawn Melton's answer yields: 46000000267600001

RESTORE HEADERONLY FROM DISK = 'C:\temp\backup test\Log1.bak'  
-- yields: 46000000267600001

Entonces parece que el primero está apagado por varios órdenes de magnitud.

Luego hice la misma prueba en SQL 2008 SP1 (10.00.2531), donde ambas consultas arrojaron la respuesta correcta.

Andreas
fuente
He estado investigando porque es una pregunta interesante, pero no estoy llegando muy lejos. No estoy seguro de que SQL admita esto de forma inmediata.
Katherine Villyard
1
Estoy seguro de que hay una forma de verificar esto, tal vez usar el LSN no sea la forma de hacerlo. Pondré una recompensa por la pregunta en unas horas, esta pregunta necesita más puntos de vista ...

Respuestas:

12

Me dirigí a mi copia de SQL Server 2008 Internals y se indicó al DMV sys.database_recovery_status para encontrar el primer LSN de la siguiente copia de seguridad de registro. Que por BOL la columna le last_log_backup_lsnproporciona:

Número de secuencia de registro de la copia de seguridad de registro más reciente. Este es el LSN final de la copia de seguridad de registro anterior y el LSN inicial de la siguiente copia de seguridad de registro.
NULL = No existe copia de seguridad de registro La base de datos está fuera de línea o la base de datos no se iniciará.

Solo para mencionar también que Kalen también trae a colación el punto de que obtendrá un valor NULL si la base de datos está en modo de recuperación SIMPLE (modo de autotruncamiento) o si no existe una copia de seguridad de registro.

Pero, ¿cómo puedo obtener el FirstLSN del registro de cola?

Sin realmente hacer una copia de seguridad del registro de cola de una base de datos (no tengo una instancia de prueba para probar esto), podría concluir lógicamente que el valor devuelto en la columna mencionada sería el primer LSN de la siguiente copia de seguridad de registro, en su caso el cola.

Por lo tanto, ejecutar lo siguiente devolverá el valor que creo que está buscando:


SELECT 
   last_log_backup_lsn
FROM 
   sys.database_recovery_status
WHERE 
   databse_id = DB_ID('MyDb')

Este DMV está disponible a partir de SQL 2005.

EDITAR
A menos que lea el enlace de BOL, tenga en cuenta que este DMV solo devolverá valores a las bases de datos que están en línea, o se abrirán cuando BOL lo haga referencia. Si ocurre una falla que requiere que realice una copia de seguridad del registro de cola de una base de datos, no podrá verificar este valor a través del código anterior a menos que la base de datos sea accesible; que en un fracaso probablemente no lo sería.


fuente
El resultado de esta consulta parece ser correcto.
Andreas
Ciertamente me parece correcto. Last_log_backup_lsn es igual a first_lsn de la cola del registro. Entonces, si tiene un archivo de registro para restaurar con un last_lsn igual a last_log_backup_lsn del código de Shawn, entonces sabe que tiene una copia de seguridad hasta el registro de cola. (Por supuesto, eso solo se garantiza como verdadero en el momento de la consulta, al momento siguiente podría iniciarse una nueva copia de seguridad del registro).
RLF
@RLF agregó una nota adicional porque esto también sería cierto si la base de datos no es accesible. Realmente no es una solución viable para usar cuando se necesita implementar su plan de recuperación ante desastres. Solo para ejercicios de mesa o para probar su plan.
6

Algo como lo siguiente debería hacerlo.

WITH LSN_CTE
AS
(
SELECT TOP 1
       LEFT( LogRecords.[Current LSN], 8 )          AS Part1,
       SUBSTRING( LogRecords.[Current LSN], 10, 8 ) AS Part2,
       RIGHT( LogRecords.[Current LSN], 4 )         AS Part3
FROM   sys.fn_dblog(NULL,NULL) AS LogRecords
ORDER BY [Current LSN]
)
SELECT CAST( CAST( CONVERT( varbinary, Part1, 2 ) AS int ) AS varchar ) +
       RIGHT( '0000000000' + CAST( CAST( CONVERT( varbinary, Part2, 2 ) AS int ) AS varchar ), 10 ) +
       RIGHT( '00000'      + CAST( CAST( CONVERT( varbinary, Part3, 2 ) AS int ) AS varchar ), 5 ) AS [Converted LSN]
FROM   LSN_CTE

Usando el código de conversión a decimal de este artículo .

El ORDER BY [Current LSN]bien puede ser una sobrecarga completamente innecesaria. No estoy seguro. El resultado de esta función siempre parece estar en orden LSN y supongo que solo lee el registro secuencialmente, pero por si acaso ...

Martin Smith
fuente
@MartinSmith: fn_dblogno parece estar muy bien documentado. Supongo que sus resultados siempre se mantienen para la base de datos actual (ya que no hay WHERE DbName = 'XXX'en el fragmento).
Andreas
@Andreas - Sí, no está documentado. Y sí, devuelve la información del registro de la base de datos actual.
Martin Smith
Vea mi edición de la pregunta original. El número devuelto por su fragmento es mucho mayor que el LSN de las copias de seguridad recientes del mismo DB.
Andreas
@Andreas - Extraño. Solo lo probé en un único DB de prueba y funcionó correctamente. No estoy seguro de dónde está el error. ¿En qué versión de SQL Server está ejecutando esto? El CONVERTparámetro con estilo 2podría ser el problema.
Martin Smith
(Aunque la respuesta de Shawn parece masivamente preferible a esta de todos modos)
Martin Smith