1+ SET NOCOUNT ON ;
2+
3+ DECLARE @DBName SYSNAME = N ' DeineDatenbank' ;
4+ DECLARE @ReserveAfterShrinkMB INT = 512 ; -- freier Puffer nach dem Shrink
5+ DECLARE @MinimumTargetSizeMB INT = 256 ; -- Logdatei nie kleiner als dieser Wert
6+ DECLARE @MinShrinkGainMB INT = 256 ; -- nur shrinken, wenn mindestens so viele MB frei werden
7+
8+ DECLARE @RecoveryModelBefore NVARCHAR (60 );
9+ DECLARE @RecoveryModelAfter NVARCHAR (60 );
10+ DECLARE @LogReuseWaitDesc NVARCHAR (120 );
11+
12+ DECLARE @LogSizeMB DECIMAL (18 ,2 );
13+ DECLARE @LogUsedPct DECIMAL (18 ,2 );
14+ DECLARE @LogUsedMB DECIMAL (18 ,2 );
15+ DECLARE @LogFreeMB DECIMAL (18 ,2 );
16+
17+ DECLARE @LogFileCount INT ;
18+ DECLARE @LogFileId INT ;
19+
20+ DECLARE @ShrinkTargetMB INT ;
21+ DECLARE @ShrinkGainMB DECIMAL (18 ,2 );
22+
23+ DECLARE @sql NVARCHAR (MAX );
24+ DECLARE @Action NVARCHAR (4000 ) = N ' ' ;
25+ DECLARE @DidShrink BIT = 0 ;
26+
27+ IF DB_ID (@DBName) IS NULL
28+ BEGIN
29+ THROW 50000 , ' Die angegebene Datenbank existiert nicht.' , 1 ;
30+ END ;
31+
32+ IF OBJECT_ID (' tempdb..#LogSpace' ) IS NOT NULL
33+ DROP TABLE #LogSpace;
34+
35+ CREATE TABLE #LogSpace
36+ (
37+ [Database Name] SYSNAME ,
38+ [Log Size (MB)] DECIMAL (18 ,2 ),
39+ [Log Space Used (%)] DECIMAL (18 ,2 ),
40+ [Status] INT
41+ );
42+
43+ INSERT INTO #LogSpace
44+ EXEC (' DBCC SQLPERF(LOGSPACE)' );
45+
46+ SELECT
47+ @RecoveryModelBefore = d .recovery_model_desc ,
48+ @LogReuseWaitDesc = d .log_reuse_wait_desc ,
49+ @LogSizeMB = ls.[Log Size (MB)],
50+ @LogUsedPct = ls.[Log Space Used (%)],
51+ @LogUsedMB = CAST (ls.[Log Size (MB)] * ls.[Log Space Used (%)] / 100 .0 AS DECIMAL (18 ,2 )),
52+ @LogFreeMB = CAST (ls.[Log Size (MB)] * (100 .0 - ls.[Log Space Used (%)]) / 100 .0 AS DECIMAL (18 ,2 ))
53+ FROM sys .databases AS d
54+ INNER JOIN #LogSpace AS ls
55+ ON ls.[Database Name] = d .name
56+ WHERE d .name = @DBName;
57+
58+ SELECT
59+ @LogFileCount = COUNT (* ),
60+ @LogFileId = CASE WHEN COUNT (* ) = 1 THEN MAX (file_id ) END
61+ FROM sys .master_files
62+ WHERE database_id = DB_ID (@DBName)
63+ AND type = 1 ; -- LOG
64+
65+ SELECT
66+ [Step] = ' Before' ,
67+ DatabaseName = @DBName,
68+ RecoveryModel = @RecoveryModelBefore,
69+ LogReuseWaitDesc = @LogReuseWaitDesc,
70+ LogFileCount = @LogFileCount,
71+ LogSizeMB = @LogSizeMB,
72+ LogUsedPct = @LogUsedPct,
73+ LogUsedMB = @LogUsedMB,
74+ LogFreeMB = @LogFreeMB;
75+
76+ IF @RecoveryModelBefore <> N ' SIMPLE'
77+ BEGIN
78+ SET @sql = N ' ALTER DATABASE ' + QUOTENAME (@DBName) + N ' SET RECOVERY SIMPLE;' ;
79+ EXEC sys .sp_executesql @sql;
80+ SET @Action = N ' Recovery Model wurde auf SIMPLE gesetzt. ' ;
81+ END
82+ ELSE
83+ BEGIN
84+ SET @Action = N ' Datenbank war bereits SIMPLE. ' ;
85+ END ;
86+
87+ SET @sql = N ' USE ' + QUOTENAME (@DBName) + N ' ; CHECKPOINT;' ;
88+ EXEC sys .sp_executesql @sql;
89+
90+ TRUNCATE TABLE #LogSpace;
91+
92+ INSERT INTO #LogSpace
93+ EXEC (' DBCC SQLPERF(LOGSPACE)' );
94+
95+ SELECT
96+ @RecoveryModelAfter = d .recovery_model_desc ,
97+ @LogReuseWaitDesc = d .log_reuse_wait_desc ,
98+ @LogSizeMB = ls.[Log Size (MB)],
99+ @LogUsedPct = ls.[Log Space Used (%)],
100+ @LogUsedMB = CAST (ls.[Log Size (MB)] * ls.[Log Space Used (%)] / 100 .0 AS DECIMAL (18 ,2 )),
101+ @LogFreeMB = CAST (ls.[Log Size (MB)] * (100 .0 - ls.[Log Space Used (%)]) / 100 .0 AS DECIMAL (18 ,2 ))
102+ FROM sys .databases AS d
103+ INNER JOIN #LogSpace AS ls
104+ ON ls.[Database Name] = d .name
105+ WHERE d .name = @DBName;
106+
107+ SET @ShrinkTargetMB =
108+ CASE
109+ WHEN CEILING (@LogUsedMB + @ReserveAfterShrinkMB) > @MinimumTargetSizeMB
110+ THEN CAST (CEILING (@LogUsedMB + @ReserveAfterShrinkMB) AS INT )
111+ ELSE @MinimumTargetSizeMB
112+ END ;
113+
114+ SET @ShrinkGainMB = CAST (@LogSizeMB - @ShrinkTargetMB AS DECIMAL (18 ,2 ));
115+
116+ SELECT
117+ [Step] = ' After Recovery Change / Checkpoint' ,
118+ DatabaseName = @DBName,
119+ RecoveryModel = @RecoveryModelAfter,
120+ LogReuseWaitDesc = @LogReuseWaitDesc,
121+ LogFileCount = @LogFileCount,
122+ LogSizeMB = @LogSizeMB,
123+ LogUsedPct = @LogUsedPct,
124+ LogUsedMB = @LogUsedMB,
125+ LogFreeMB = @LogFreeMB,
126+ ShrinkTargetMB = @ShrinkTargetMB,
127+ ShrinkGainMB = @ShrinkGainMB;
128+
129+ IF @LogFileCount <> 1
130+ BEGIN
131+ SET @Action = @Action + N ' Kein Shrink durchgeführt, da die Datenbank nicht genau eine Logdatei hat.' ;
132+ END
133+ ELSE IF @ShrinkGainMB < @MinShrinkGainMB
134+ BEGIN
135+ SET @Action = @Action + N ' Kein Shrink durchgeführt, da das Shrink-Potenzial kleiner als der Schwellwert ist.' ;
136+ END
137+ ELSE IF @ShrinkTargetMB >= CEILING (@LogSizeMB)
138+ BEGIN
139+ SET @Action = @Action + N ' Kein Shrink durchgeführt, da die Zielgröße nicht kleiner als die aktuelle Größe ist.' ;
140+ END
141+ ELSE
142+ BEGIN
143+ SET @sql =
144+ N ' USE ' + QUOTENAME (@DBName) + N' ;
145+ DBCC SHRINKFILE (' + CAST (@LogFileId AS NVARCHAR (20 )) + N ' , ' + CAST (@ShrinkTargetMB AS NVARCHAR (20 )) + N ' );' ;
146+
147+ EXEC sys .sp_executesql @sql;
148+
149+ SET @DidShrink = 1 ;
150+ SET @Action = @Action + N ' Logdatei wurde geschrumpft.' ;
151+ END ;
152+
153+ TRUNCATE TABLE #LogSpace;
154+
155+ INSERT INTO #LogSpace
156+ EXEC (' DBCC SQLPERF(LOGSPACE)' );
157+
158+ SELECT
159+ @LogReuseWaitDesc = d .log_reuse_wait_desc ,
160+ @LogSizeMB = ls.[Log Size (MB)],
161+ @LogUsedPct = ls.[Log Space Used (%)],
162+ @LogUsedMB = CAST (ls.[Log Size (MB)] * ls.[Log Space Used (%)] / 100 .0 AS DECIMAL (18 ,2 )),
163+ @LogFreeMB = CAST (ls.[Log Size (MB)] * (100 .0 - ls.[Log Space Used (%)]) / 100 .0 AS DECIMAL (18 ,2 ))
164+ FROM sys .databases AS d
165+ INNER JOIN #LogSpace AS ls
166+ ON ls.[Database Name] = d .name
167+ WHERE d .name = @DBName;
168+
169+ SELECT
170+ [Step] = ' Final' ,
171+ DatabaseName = @DBName,
172+ RecoveryModel = @RecoveryModelAfter,
173+ LogReuseWaitDesc = @LogReuseWaitDesc,
174+ LogFileCount = @LogFileCount,
175+ LogSizeMB = @LogSizeMB,
176+ LogUsedPct = @LogUsedPct,
177+ LogUsedMB = @LogUsedMB,
178+ LogFreeMB = @LogFreeMB,
179+ ShrinkTargetMB = @ShrinkTargetMB,
180+ ShrinkPerformed = @DidShrink,
181+ ActionSummary = @Action;
0 commit comments