Wie lösche ich ein zweites Transaktionslog?

Bei einer routinemäßigen Kontrolle eines Servers fiel mir auf, dass dort jemand ein zweites Transaktionslog auf einer anderen Platte angelegt hatte, da er wohl befürchtete, dass der Plattenplatz beim ersten Transaktionslog für eine größere Transaktion nicht ausreichen würde. Bei der Bereinigung habe ich mir dann selber ein Bein gestellt.

Die Vorgeschichte

Eigentlich wollte ich nur die Datenbanken kontrollieren, die zu viele VLFs haben. Details dazu habe ich ja bereits früher in meinem Artikel über VLFs beschrieben.

Bei dieser Datenbank (die aktuell nicht in Benutzung war) habe ich dann gesehen, dass es zwei LDFs gibt und das erste auf einer Partition lag, wo nicht besonders viel Platz war. Die "AutoGrow" Option war dort deaktiviert, damit es keine Probleme geben konnte. Im ersten Schritt habe ich dieses LDF mal deutlich verkleinert wie oben beschrieben, damit die geplante Kopieraktion schneller geht. Dann habe ich die Datenbank kurz Offline genommen und das (kleine) LDF auf die andere Partition verschoben. Datenbank wieder Online gesetzt und nun sollte im zweiten Schritt das überflüssige Transaktionsprotokoll verschwinden.

Transaktionsprotokoll entfernen

Zum entfernen des Transaktionsprotokolls sind nur ein paar Schritte notwendig, da ein gefülltes Transaktionsprotokoll nicht gelöscht werden kann. USE [MeineDatenbank]
GO

DBCC SHRINKFILE(3, EMPTYFILE);

BACKUP LOG [MeineDatenbank] TO  DISK = N'H:\Backup\TRN\MeineDatenbank\MeineDatenbank_backup_log_cmu_1.trn' WITH NOFORMAT, INIT;
GO

ALTER DATABASE [MeineDatenbank]  REMOVE FILE [MeineDatenbank2_log];
GO

Aber in diesem Falle konnte ich das Transaktionsprotokoll nicht löschen, da ich folgende Meldung erhielt:

Msg 5042, Level 16, State 2, Line 1
The file 'MeineDatenbank2_log' cannot be removed because it is not empty.

Wie kann das denn sein? Schauen wir mal in der sys.databases nach, ob dort etwas steht:

SELECT log_reuse_wait_desc
FROM MASTER.sys.databases
WHERE name = 'MeineDatenbank';

Das Ergebnis war nicht unerwartet, aber trotzdem nicht so hilfreich: NOTHING

Weitere Ursachenforschung

Schauen wir uns mal genau an, ob sich vielleicht der aktive Teil des Logs in der zu löschenden Datei befindet und wie die beiden Transaktionslogs intern aufgebaut sind.

DBCC Loginfo

Die Datei mit FileId 3 soll gelöscht werden, alle VLFs haben dort den Status 0. Wo ist das Problem?

Bei Paul Randall war das Problem sehr schön beschrieben. Eine Datenbank muss immer wenigstens zwei VLFs haben. Wenn jetzt das übrigbleibende Transaktionslog (aufgrund meiner Bereinigung) nur ein VLF hat, kann das zweite nicht gelöscht werden. Die Fehlermeldung ist nicht nur irreführend, sondern falsch. Denn "Empty" war es ja auf jeden Fall. Der Trick besteht also darin, dem ersten Transaktionslog zu weiteren VLFs zu verhelfen. Nichts leichter als das:

ALTER DATABASE [MeineDatenbank] Modify FILE (NAME = N'MeineDatenbank_log', SIZE = 2000MB , FILEGROWTH = 2000MB);

Nun funktioniert auch dieser Befehl und das Ergebnis ist eine Datenbank mit einem Transaktionslog:

ALTER DATABASE [MeineDatenbank]  REMOVE FILE [MeineDatenbank2_log];

Falls jemand diese Situation einmal nachstellen möchte, findet er in dem oben genannten Artikel von Paul Randall auch ein Skript, welches dieses Szenario schnell herstellt.