DBCC SHRINKFILE in der Protokolldatei reduziert die Größe auch nach dem BACKUP LOG TO DISK nicht

77

Ich habe eine Datenbank [Meine Datenbank] mit folgenden Informationen:
SQL Server 2008
MDF-Größe: 30 GB
LDF-Größe: 67 GB

Ich wollte die Protokolldatei so weit wie möglich verkleinern und begann meine Suche, um herauszufinden, wie das geht. Vorsichtsmaßnahme: Ich bin kein DBA (oder nähere mich sogar einem DBA) und habe mich durch diese Suche gefühlsmäßig weiterentwickelt.

Zuerst habe ich nur SSMS, DB-Eigenschaften, Dateien aufgerufen und den Wert für die Anfangsgröße (MB) auf 10 bearbeitet. Dadurch wurde die Protokolldatei auf 62 GB reduziert (nicht genau die 10 MB, die ich eingegeben habe). Also habe ich SQL Profiler angehängt und gesehen, dass DBCC SHRINKFILE aufgerufen wurde. Ich habe diesen Befehl dann in den Abfrageeditor eingegeben und hier sind die Ergebnisse.

DBCC SHRINKFILE (N'My DB_Log' , 10)

Und die Ausgabe war:

Cannot shrink log file 2 (My DB_Log) because the logical log file located at the end of the file is in use.
DbId   FileId      CurrentSize MinimumSize UsedPages   EstimatedPages
------ ----------- ----------- ----------- ----------- --------------
8      2           8044104     12800       8044104     12800

(1 row(s) affected)

DBCC execution completed. If DBCC printed error messages, contact your system administrator.

Ich habe dann einige Nachforschungen angestellt und Folgendes gefunden:

http://support.microsoft.com/kb/907511

Was bedeutet, dass ich die Protokolldatei vor dem Shrinkfile sichern muss, damit die virtuellen Protokolldateien freigegeben werden und das Shrinkfile seine Arbeit erledigen kann - ich weiß nicht, was das bedeutet ... ich paraphrasiere hier nur :)

Also dachte ich mir, ich würde versuchen, die Protokolldatei zu sichern und dann eine DBCC-SHRINKFILE auszuführen (und ich habe die Größe der neuen Protokolldatei auf 12800 geändert, da dies die in der Ausgabe des vorherigen DBCC-SHRINKFILE-Befehls angegebene Mindestgröße war).

BACKUP LOG [My DB] TO DISK = 'D:\SQLBackup\20110824-MyDB-Log.bak'
GO
DBCC SHRINKFILE (N'My DB_Log' , 12800)
GO

Das Ergebnis war das gleiche wie beim ersten Mal. Ich kann die Protokolldatei nur auf 62 GB reduzieren.

Ich bin mir nicht sicher, was ich falsch mache und was ich als nächstes versuchen soll.

Ed Sinek
quelle
Um dies zu verhindern, sollten Sie Protokollsicherungen ausführen oder den Wiederherstellungsmodus auf einfach einstellen.
DForck42
3
Mein Problem war ein PAUSED REPLICATION / MIRRORING-Setup - es scheint, dass SQL Tlogs nicht verkleinert, wenn es glaubt, dass es sie für die Replikation benötigt. Dies wird wahrscheinlich nicht das Problem vieler Menschen sein, aber es könnte einigen helfen.
Pettys

Antworten:

43

Zusätzlich zu den Schritten, die Sie bereits ausgeführt haben, müssen Sie den Wiederherstellungsmodus auf einfach einstellen, bevor Sie das Protokoll verkleinern können.

Dies ist keine empfohlene Vorgehensweise für Produktionssysteme. Sie verlieren Ihre Fähigkeit, sich von früheren Sicherungen / Protokolldateien zu einem bestimmten Zeitpunkt wiederherzustellen.

Ein Beispiel und eine Erläuterung finden Sie in Beispiel B auf dieser DBCC SHRINKFILE (Transact-SQL) msdn-Seite.

jlnorsworthy
quelle
Gibt es aus Neugier eine Möglichkeit, den Wiederherstellungsmodus anhand der SSMS-Benutzeroberfläche zu ermitteln? Ich habe die DB-Eigenschaften durchgesehen, aber nicht gesehen. Am nächsten war die Seite Eigenschaften / Optionen, auf der der Wert für Wiederherstellung / PageVerify angezeigt wird.
Ed Sinek
Gefunden - es ist nicht in der Liste der "anderen Optionen". Es befindet sich oben auf der Seite - eines der drei Dropdowns. Danke.
Ed Sinek
5
Ich wollte vorschlagen, diese Abfrage auszuführen: Wählen Sie recovery_model_desc aus sys.databases aus, wobei name = 'database name'
jlnorsworthy
Vielen Dank. Das Wiederherstellungsmodell zu ändern war der Schlüssel :)
Alireza
133

Okay, hier ist eine Lösung, um die physische Größe der Transaktionsdatei zu reduzieren, ohne jedoch den Wiederherstellungsmodus auf einfach zu ändern.

Suchen Sie in Ihrer Datenbank die Datei-ID der Protokolldatei mithilfe der folgenden Abfrage.

SELECT * FROM sys.database_files;

In meinem Fall lautet die Protokolldatei file_id 2. Jetzt möchten wir die verwendeten virtuellen Protokolle suchen und dies mit dem folgenden Befehl tun.

DBCC LOGINFO;

Hier können Sie sehen, ob virtuelle Protokolle verwendet werden, indem Sie feststellen, ob der Status 2 (in Verwendung) oder 0 (kostenlos) ist. Beim Verkleinern von Dateien werden leere virtuelle Protokolle ab dem Ende der Datei physisch entfernt, bis der erste verwendete Status erreicht ist. Aus diesem Grund wird eine Transaktionsprotokolldatei manchmal teilweise verkleinert, jedoch nicht alle freien virtuellen Protokolle entfernt.

Wenn Sie einen Status 2 bemerken, der nach 0 auftritt, blockiert dies die vollständige Verkleinerung der Datei. Um dies zu umgehen, führen Sie eine weitere Transaktionsprotokollsicherung durch und führen Sie diese Befehle sofort aus. Geben Sie dabei die oben angegebene Datei-ID und die Größe an, auf die Ihre Protokolldatei reduziert werden soll.

-- DBCC SHRINKFILE (file_id, LogSize_MB)
DBCC SHRINKFILE (2, 100);
DBCC LOGINFO;

Dadurch wird die Zuordnung der virtuellen Protokolldatei angezeigt, und Sie werden hoffentlich feststellen, dass sie etwas reduziert wurde. Da virtuelle Protokolldateien nicht immer in der richtigen Reihenfolge zugewiesen werden, müssen Sie das Transaktionsprotokoll möglicherweise einige Male sichern und diese letzte Abfrage erneut ausführen . Aber normalerweise kann ich es innerhalb von ein oder zwei Backups verkleinern.

Radderz
quelle
6
Lief wie am Schnürchen. Das 99% kostenlose Backup-Protokoll dauerte nur eine Sekunde und die Datei stieg sofort von über 22.000 MB auf 200 MB. Dies sollte als die richtige Antwort markiert werden.
Triynko
Ich schätze die Hintergrundinformationen. Ich stecke jedoch immer noch fest, weil ich denke, dass Ihre Lösung auf die Lösung hinausläuft, die das Originalplakat versucht hat und die nicht funktionieren konnte. Ist Ihre Lösung im Grunde, "BACKUP LOG ... GO DBCC SHRINKFILE ..." mehrmals auszuführen, bis es funktioniert? Ich habe es mehrmals ohne Erfolg versucht, und es scheint, als hätte das OP es auch ohne Erfolg versucht. Ich möchte nur klarstellen, ob mir etwas in Ihrer Antwort fehlt.
Pettys
3
UPDATE: Mein Problem war, dass ein angehaltenes Replikations- / Spiegelungs-Setup das tlog sperrte. Wahrscheinlich ein kleiner Randfall.
Pettys
4
@pettys Ja, wenn Sie die Datei auf die niedrigstmögliche Größe verkleinern möchten, müssen Sie eine Sicherung, eine Verkleinerung, eine Sicherung und eine Verkleinerung auf einmal durchführen. Der Grund (ich denke, es ist beabsichtigt) ist, dass der Verkleinerer nur die Größe der Protokolldatei auf die Größe der 'verwendeten Seiten' seit der letzten Sicherung reduziert; Wahrscheinlich, um die Notwendigkeit zu minimieren, die Protokolldatei zu vergrößern. Dies ist nützlich für Produktionsumgebungen, in denen regelmäßig geladen und gesichert wird. Das Obige versucht dies zu demonstrieren und zu debuggen. Wenn Ihre Protokolldatei Nullen enthält, kann diese weiter verkleinert werden. Wenn nicht, kann es zu Problemen beim Freigeben von Seiten Ihrer gesicherten Protokolle kommen.
Radderz
13

Ich verwende dieses Skript auf SQL Server 2008 R2.

USE [db_name]

ALTER DATABASE [db_name] SET RECOVERY SIMPLE WITH NO_WAIT

DBCC SHRINKFILE([log_file_name]/log_file_number, wanted_size)

ALTER DATABASE [db_name] SET RECOVERY FULL WITH NO_WAIT
Manit
quelle
6
Und wenn Sie dies tun, haben Sie Ihre Transaktionsprotokoll-Sicherungskette BUSTIERT - so dass Sie im Falle einer Katastrophe nach dem Zurücksetzen auf die vollständige Wiederherstellung 100% Daten verlieren, es sei denn, Sie starten danach entweder eine vollständige oder eine DIFF-Sicherung Zurücksetzen auf RECOVERY FULL.Auch mit NO_WAIT bedeutet, dass Sie Transaktionen während des Flugs KEINE Zeit zum Abschließen geben. Eine bessere Option wäre MIT ROLLBACK NACH 10 SEKUNDEN (oder ähnlichem).
Michael K. Campbell
Wie bekomme ich log_file_name oder Nummer?
Kiquenet
10

Versuche dies

ALTER DATABASE XXXX  SET RECOVERY SIMPLE

use XXXX

declare @log_File_Name varchar(200) 

select @log_File_Name  = name from sysfiles where filename like '%LDF'

declare @i int = FILE_IDEX ( @log_File_Name)

dbcc shrinkfile ( @i , 50) 
user2630576
quelle
2

Ich habe viele Möglichkeiten ausprobiert, aber das funktioniert.

Der Beispielcode ist in DBCC SHRINKFILE verfügbar

USE DBName;  
GO  
-- Truncate the log by changing the database recovery model to SIMPLE.  
ALTER DATABASE DBName  
SET RECOVERY SIMPLE;  
GO  
-- Shrink the truncated log file to 1 MB.  
DBCC SHRINKFILE (DBName_log, 1);  --File name SELECT * FROM sys.database_files; query to get the file name
GO  
-- Reset the database recovery model.  
ALTER DATABASE DBName  
SET RECOVERY FULL;  
GO
Sathish
quelle
1
Dies ist eine wirklich schlechte Idee, sie wird in der aktuell akzeptierten Antwort mit einem Haftungsausschluss angeboten, warum es SCHLECHT ist!
James Jenkins
0

Ich habe dieses Problem gelöst, indem ich die vollständige und transaktionale Sicherung durchgeführt habe. Manchmal ist der Sicherungsvorgang nicht abgeschlossen und dies ist einer der Gründe, warum die .ldf-Datei nicht verkleinert wird. Versuche dies. Es hat bei mir funktioniert.

Swapnil Gaikwad
quelle
-1

Vielen Dank an @ user2630576 und @ Ed.S.

Das Folgende war ein Vergnügen:

BACKUP LOG [database] TO DISK = 'D:\database.bak'
GO

ALTER DATABASE [database] SET RECOVERY SIMPLE

use [database]

declare @log_File_Name varchar(200)

select @log_File_Name = name from sysfiles where filename like '%LDF'

declare @i int = FILE_IDEX ( @log_File_Name)

dbcc shrinkfile ( @i , 50)

ALTER DATABASE [database] SET RECOVERY FULL
Aussie Ash
quelle
Dies ist eine wirklich schlechte Idee, sie wird in der aktuell akzeptierten Antwort mit einem Haftungsausschluss angeboten, warum es SCHLECHT ist!
James Jenkins