SQL Server:Shrinking All dbs Transaction Log (Transaction Log Shrinking) use script
Predict the DBCC SHRINK DATABASE finish time
SELECT session_id,percent_complete,DATEADD(MILLISECOND,estimated_completion_time,
CURRENT_TIMESTAMP) Estimated_finish_time, (total_elapsed_time/1000)/60 Total_Elapsed_Time_MINS , DB_NAME(Database_id) Database_Name ,command,sql_handle |
Code to shrink the all db's transaction log files:
Step1: Before processing to next step,Enable xp_cmdshell option so that OS commands can be execute through SSMS.
-- To allow advanced options to be changed.
EXEC sp_configure 'show advanced options', 1
GO
-- To update the currently configured value for advanced options.
RECONFIGURE
GO
-- To enable the feature.
EXEC sp_configure 'xp_cmdshell', 1
GO
-- To update the currently configured value for this feature.
RECONFIGURE
GO
|
Step2: Script File: ShrinkTransactionLog.sql
Copy and paste the below content in ShrinkTransactionLog.sql. Make sure you run the script once in SSMS.
--eazybi_jira
--Trim DECLARE @DBName AS NVARCHAR(100), @LogFileName AS NVARCHAR(100), @exec_stmt nvarchar(625) SET NOCOUNT ON --——————————————————————————- --create the temporary table to hold the log file names --—————————————————————————– --Drop table #logfiles CREATE TABLE #logfiles ( dbname NVARCHAR(100), filename NVARCHAR(100), ) --—————————————————————————– --select all dbs, except for system dbs --—————————————————————————– DECLARE curDBName CURSOR FOR SELECT [name] FROM master.sys.databases WHERE name NOT IN ('master', 'tempdb', 'model', 'msdb') AND state_desc = 'ONLINE' --——————————————————————————- --add the log file name to the temporary table,groupid=0 is for logfile and 1 for datafile. --—————————————————————————– OPEN curDBName FETCH NEXT FROM curDBName INTO @DBName WHILE @@FETCH_STATUS = 0 BEGIN SELECT @exec_stmt = 'INSERT INTO #logfiles SELECT ''' + @DBName + ''' , name FROM ' + quotename(@DBName, N'[') + N'.dbo.sysfiles WHERE groupid = 0' EXECUTE (@exec_stmt) FETCH NEXT FROM curDBName INTO @DBName END CLOSE curDBName DEALLOCATE curDBName --SELECT * FROM #logfiles ------------------------------------------------ --select all log filenames from the #logiles ------------------------------------------------- DECLARE curLogName CURSOR FOR SELECT dbname, [filename] FROM #logfiles --—————————————————————————- --shrink all log files --—————————————————————————– OPEN curLogName FETCH NEXT FROM curLogName INTO @DBName, @LogFileName WHILE @@FETCH_STATUS = 0 BEGIN --SELECT @exec_stmt = ' USE ' + quotename(@DBName) + N' DBCC SHRINKFILE (' + quotename(@LogFileName)+')' SELECT @exec_stmt = 'USE [' + @DBName + '] ' + 'ALTER DATABASE [' + @DBName + '] SET RECOVERY SIMPLE WITH NO_WAIT ' + 'DBCC SHRINKFILE(N''' + @LogFileName + ''', 1) ' + 'ALTER DATABASE [' + @DBName + '] SET RECOVERY FULL WITH NO_WAIT' print (@exec_stmt) EXECUTE (@exec_stmt) FETCH NEXT FROM curLogName INTO @DBName, @LogFileName END CLOSE curLogName DEALLOCATE curLogName --—————————————- --clean up the logfile table --—————————————- DROP TABLE #logfiles |
Step3: Script to Iterate through All SQL Instances
There are many ways to execute SQL’s or T-SQL’s across listed SQL Instances.
A script or SQL’s need to be executed across ‘N’ number of instances. This example which does just one way activity. In my upcoming post, I’ll explain how to pull and store the data on a centralized server.
A script or SQL’s need to be executed across ‘N’ number of instances. This example which does just one way activity. In my upcoming post, I’ll explain how to pull and store the data on a centralized server.
This component is enabled where you are intended to run the script(Centralized Server).
In this example,
In this example,
1. servernames are listed in C:\servers.txt
2. T-SQL’s are in c:\ShrinkTransactionLog.sql..
After enabling XP_CMDSHELL and placing both the files on Centralized Server,
open SSMS(Management Studio) and execute the below script
Input File:
List the servernames under Servers.txt
Copy and paste the below content in servers.txt .
KPDBQ001
KPDBQ002
|
Open SSMS and execute below T-SQL
Master..xp_cmdshell ‘for /f %j in (c:\servers.txt) do sqlcmd -S %j -i c:\Transaction.sql -E >>c:\ShrinkOutput.txt’
|
Output : ShrinkOutput.txt
if ‘?’ <> ‘master’ and ‘?’ <> ‘msdb’ and ‘?’<>’tempdb’ and ‘?’ <> ‘model’ BEGIN USE [?]; SELECT ‘?’; DECLARE @LogFile varchar (30); SELECT @LogFile = name FROM dbo.sysfiles WHERE (status & 0×40) <> 0; dbcc shrinkfile (@LogFile); END
(1 rows affected)
-----------------------------------------------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------------------------------------------
Method:2
Before Shining Transaction Log Size
However, in my case, an enterprise edition SharePoint 2010 server has more than 32 databases, so that's why I quite reluctantly execute the script repeatedly for that many databases, not to mention, it's quite easy to case human error as well.
Before Shining Transaction Log Size
SELECT DB_NAME(database_id) AS DatabaseName,
Name AS Logical_Name, Physical_Name, size,(size*8)/1024 SizeMB FROM sys.master_files order by size desc |
However, in my case, an enterprise edition SharePoint 2010 server has more than 32 databases, so that's why I quite reluctantly execute the script repeatedly for that many databases, not to mention, it's quite easy to case human error as well.
First off, I created a temp table #
TransactionLogFiles
, by which I store all the database and log files name in there, so that I could shrink the log files later on:
CREATE TABLE #TransactionLogFiles (DatabaseName VARCHAR(150), LogFileName VARCHAR(150) )
-- step 1. get hold of the entire database names from the database server DECLARE DataBaseList CURSOR FOR SELECT name FROM SYS.sysdatabases WHERE NAME NOT IN ('master','tempdb','model','msdb','distribution') |
Then, after knowing the database name, I could quickly work out the corresponding log files name and insert all their details into the temp table #
TransactionLogFiles
I created in the previous step by utilizing a SQL Cursor
DECLARE @DataBase VARCHAR(128)
DECLARE @SqlScript VARCHAR(MAX) -- step 2. insert all the database name and corresponding log files' names into the temp table OPEN DataBaseList FETCH NEXT FROM DataBaseList INTO @DataBase WHILE @@FETCH_STATUS <> -1 BEGIN SET @SqlScript = 'USE [' + @DataBase + '] INSERT INTO #TransactionLogFiles(DatabaseName, LogFileName) SELECT ''' + @DataBase + ''', Name FROM sysfiles WHERE FileID=2' --SELECT @SqlScript EXEC(@SqlScript) FETCH NEXT FROM DataBaseList INTO @DataBase END DEALLOCATE DataBaseList |
Lastly, iterate each row from the temp table #
TransactionLogFiles
, then change the database recovery mode to "simple", pass the checkpoint, then shrink the corresponding log file, switch back the database recovery mode back to "full" once the truncation has completed.
-- step 3. go through the each row and execute the shrinkfile script against each database log file on the server
DECLARE TransactionLogList CURSOR FOR SELECT DatabaseName, LogFileName FROM #TransactionLogFiles DECLARE @LogFile VARCHAR(128) OPEN TransactionLogList FETCH NEXT FROM TransactionLogList INTO @DataBase, @LogFile WHILE @@FETCH_STATUS <> -1 BEGIN SELECT @SqlScript = 'USE [' + @DataBase + '] ' + 'ALTER DATABASE [' + @DataBase + '] SET RECOVERY SIMPLE WITH NO_WAIT ' + 'DBCC SHRINKFILE(N''' + @LogFile + ''', 1) ' + 'ALTER DATABASE [' + @DataBase + '] SET RECOVERY FULL WITH NO_WAIT' EXEC(@SqlScript) FETCH NEXT FROM TransactionLogList INTO @DataBase, @LogFile END DEALLOCATE TransactionLogList --SELECT * FROM #TransactionLogFiles -- step 4. clean up DROP TABLE #TransactionLogFiles |
After Shining Transaction Log Size
SELECT DB_NAME(database_id) AS DatabaseName,
Name AS Logical_Name, Physical_Name, size,(size*8)/1024 SizeMB FROM sys.master_files order by size desc |