La restauration de la sauvegarde différentielle crée un fichier journal DEFUNCT?

11

Voici mon problème. J'essaie de déplacer une base de données vers un nouveau serveur via une restauration complète, puis de basculer avec une sauvegarde / restauration différentielle rapide. Je peux effectuer une restauration complète sans problème, mais lors de la restauration de la sauvegarde différentielle, j'obtiens l'avertissement suivant:

Msg 3127, niveau 16, état 1, ligne 1 Le fichier 'Database_Log2' de la base de données restaurée 'DatabaseName' est laissé à l'état disparu car la base de données utilise le modèle de récupération simple et le fichier est marqué pour un accès en lecture-écriture. Par conséquent, seuls les fichiers en lecture seule peuvent être récupérés par restauration fragmentaire.

La base de données est restaurée et est considérée en ligne, mais toute opération de sauvegarde échoue en raison de ce fichier DEFUNCT avec l'erreur suivante:

Msg 3636, niveau 16, état 2, ligne 1 Une erreur s'est produite lors du traitement des métadonnées «BackupMetadata» pour l'ID de base de données id de fichier 10. Msg 3046, niveau 16, état 2, ligne 1 Des métadonnées incohérentes ont été rencontrées. La seule opération de sauvegarde possible est une sauvegarde du journal de fin à l'aide de l'option WITH CONTINUE_AFTER_ERROR ou NO_TRUNCATE. Msg 3013, niveau 16, état 1, ligne 1 BASE DE DONNÉES DE SAUVEGARDE se termine anormalement.

Si je fais un RESTORE FILELISTONLY sur le full et le differentiel, les deux me donnent la même sortie, qui correspond à ce que je vois de sys.database_files sur la base de données source. Le serveur est SQL2012 SP1, sur l'édition Developer.

Je peux faire une sauvegarde complète, et immédiatement après faire un différentiel, et restaurer ces fichiers dans une base de données différente sur le même serveur et voir exactement le même problème, donc il y a quelque chose avec la façon dont le différentiel est créé qui cause cela. Si je restaure la sauvegarde complète AVEC RECUPERATION, il n'y a pas de problème. Je ne sais pas si ce fichier existait sur cette base de données, mais il est tout à fait possible que ce fichier existe et a été supprimé il y a longtemps. Si j'interroge sys.database_files sur la base de données restaurée, le fichier DEFUNCT a une valeur pour drop_lsn, ce qui semble le confirmer. Actuellement, dans la base de données source, il n'y a qu'un seul groupe de fichiers (PRIMARY), 4 fichiers de données et un fichier journal.

Des idées?

FilamentUnities
la source
Pourriez-vous s'il vous plaît nous montrer les instructions que vous utilisez pour effectuer les sauvegardes et les restaurations?
Jon Seigel
Rien d'extraordinaire. RESTORE DATABASE DatabaseName FROM DISK = 'D: \ Full.bak' AVEC REPLACE, NORECOVERY Puis RESTORE DATABASE DatabaseName FROM DISK = 'D: \ Diff.bak' WITH RECOVERY
FilamentUnities

Réponses:

5

Voici les étapes pour le reproduire, testées sur SQL 2012 SP1 Developer Edition. Cela ne se produit pas sur SQL 2008. Pour résumer, une base de données créée dans SQL 2012 alors que la base de données modèle est en récupération SIMPLE, qui a une sauvegarde complète effectuée alors qu'un fichier journal supplémentaire existe, ne peut pas créer de sauvegardes différentielles utilisables si ce fichier journal supplémentaire est jamais supprimé.

ALTER DATABASE [model] SET RECOVERY SIMPLE
GO
CREATE DATABASE [DefunctTest]
GO
ALTER DATABASE [DefunctTest] ADD LOG FILE ( NAME = N'DefunctTest_log2', FILENAME = N'D:\DefunctTest_log2.ldf' , SIZE = 25600KB , FILEGROWTH = 10%)
GO
BACKUP DATABASE [DefunctTest] TO DISK = 'D:\DefunctTestPostLogFile.bak' WITH INIT
GO
ALTER DATABASE [DefunctTest]  REMOVE FILE [DefunctTest_log2]
GO

BACKUP DATABASE [DefunctTest] TO DISK = 'D:\DefunctTestFull.bak' WITH INIT
GO
BACKUP DATABASE [DefunctTest] TO DISK = 'D:\DefunctTestDiff.bak' WITH DIFFERENTIAL, INIT
GO
--Show that the backups only have the one log file.
RESTORE FILELISTONLY FROM DISK = 'D:\DefunctTestFull.bak'
RESTORE FILELISTONLY FROM DISK = 'D:\DefunctTestDiff.bak'
GO
RESTORE DATABASE [DefunctTest2] FROM DISK = 'D:\DefunctTestFull.bak' WITH 
MOVE 'DefunctTest' TO 'D:\DefunctTest2.mdf',
MOVE 'DefunctTest_log' TO 'D:\DefunctTest2_log.ldf', REPLACE, NORECOVERY
GO
--This restore will have the error.
RESTORE DATABASE [DefunctTest2] FROM DISK = 'D:\DefunctTestDiff.bak' WITH RECOVERY
GO

USE [DefunctTest2]
SELECT * FROM sys.database_files
GO

J'ai soumis un élément Connect pour ce bug ici . La seule façon dont j'ai pu supprimer ce fichier disparu est de détacher la base de données et de la rattacher avec ATTACH_REBUILD_LOG.

MISE À JOUR: Le bogue qui crée ce scénario dans mon script de repro semble avoir été corrigé par ce KB: https://support.microsoft.com/en-us/kb/2830400 . D'après les commentaires, il semble qu'un correctif supplémentaire soit disponible pour SQL2012 / 2014, les scénarios semblent très similaires: https://support.microsoft.com/en-us/kb/3009576

FilamentUnities
la source
J'inclurais votre script dans les commentaires de connexion pour aider les gens à se reproduire.
Kenneth Fisher
1
Je ne reçois aucune erreur lors de l'exécution de votre script sur SQL Server 2012 Enterprise Edition, 11.0.3412 (CU9 pour SP1)
Le script de repro se trouve dans l'élément Connect, si vous cliquez sur le bouton Détails.
FilamentUnities
1
Shawn, en regardant à travers les correctifs dans les CU, je pense que celui-ci a probablement corrigé ce problème: support.microsoft.com/kb/2830400
FilamentUnities
2
J'ai eu une bataille avec cela la semaine dernière et ce fil m'aide à le trier alors merci. Il semble que le correctif se trouve dans SQL 2012 SP2 CU3: support.microsoft.com/en-us/kb/3009576
Richard