Created
May 22, 2025 14:57
-
-
Save nanoDBA/d9e6b940131816b557d8d11f7c520d73 to your computer and use it in GitHub Desktop.
π Rapidly fills a SQL Server test database log file to simulate disk full and alerting scenarios. Useful for testing error handling, monitoring, and DBA/ops automation. π
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
| File: Improved-Fill-TestLogVolume.sql | |
| Description: π Rapidly fills a SQL Server test database log file to simulate | |
| disk full and alerting scenarios. Useful for testing error | |
| handling, monitoring, and DBA/ops automation. π | |
| Purpose: Quickly consume log file space to test SQL Server's response to | |
| log growth, disk full, and alerting. Designed for use in | |
| dev/test environments only! Not for prod! β οΈ | |
| The script can optionally reserve a buffer of free space on the | |
| log drive, or attempt to fill the drive completely. See below. | |
| Created: 2025-05-14 | |
| Modified: 2025-05-20 | |
| Refactored: 2025-05-20 for idempotency and SQL Server compatibility | |
| (AI/DBA collaboration) | |
| WARNING: TEST/DEV USE ONLY! This script will fill disk space and may | |
| trigger alerts or impact system stability. Use with caution! π₯ | |
*/ | |
-- AI-Updated: 2024-05-20 12:00:00 | Marker: AIUPD-20240520120000-496d70726f7665642d46696c6c2d546573744c6f67566f6c756d652e73716c #| | |
-- ============================================================================ | |
-- Summary: | |
-- This script rapidly fills a SQL Server test database log file to simulate | |
-- disk full and alerting scenarios. It is designed for use in dev/test | |
-- environments to test error handling, monitoring, and automation. π | |
-- | |
-- Features: | |
-- - User-configurable parameters for directories, file sizes, and behavior | |
-- - Dynamic detection of default data/log directories | |
-- - Optional sparse file pre-fill using PowerShell | |
-- - High-speed log-filling loop with progress and free space checks | |
-- - Robust cleanup section (can be run standalone) | |
-- - All output is immediate and unbuffered (RAISERROR ... WITH NOWAIT) | |
-- - Control over reserved disk space buffer for safe or aggressive fill | |
-- - Snarky comments and emoji for fun and clarity | |
-- | |
-- Recommendations: | |
-- - Only use in non-production environments! β οΈ | |
-- - Monitor system alerts and disk space closely | |
-- - Use the cleanup section to remove all test artifacts and sparse files | |
-- - Adjust reserved disk space buffer as needed for your environment | |
-- - To fill the drive as much as possible, set ReservedLogDriveSpaceMB = 0 | |
-- - If you break the loop or script, run the cleanup section manually | |
-- | |
-- Reserved Disk Space Buffer (ReservedLogDriveSpaceMB): | |
-- - This parameter controls how much free space (in MB) to leave on the log | |
-- drive after filling. It is used to avoid completely filling the drive, | |
-- which can cause system instability. | |
-- - Set to NULL (default): Auto-calculate as 2% of free space or 512 MB min. | |
-- - Set to a specific value (e.g., 1000): Reserve that many MB free. | |
-- - Set to 0: Attempt to fill the drive completely (dangerous, for test only). | |
-- | |
-- Examples: | |
-- ('ReservedLogDriveSpaceMB', NULL) -- Auto-calc (safe-ish default) | |
-- ('ReservedLogDriveSpaceMB', 1000) -- Leave 1 GB free | |
-- ('ReservedLogDriveSpaceMB', 0) -- Fill drive as much as possible! π₯ | |
-- | |
-- ============================================================================ | |
-- ============================================= | |
-- USER CONFIGURABLE PARAMETERS (EDIT BELOW) | |
-- ============================================= | |
-- All user parameters are now stored in a temp table for robust scope. | |
-- Edit these values to control script behavior. π | |
IF OBJECT_ID('tempdb..#params') IS NOT NULL DROP TABLE #params; | |
CREATE TABLE #params ( | |
param_name NVARCHAR(100) PRIMARY KEY, | |
param_value SQL_VARIANT | |
); | |
-- Insert user parameters with comments for each | |
INSERT INTO #params (param_name, param_value) VALUES | |
('OverrideDataDir', NULL), -- Optional: override data directory (e.g. 'D:\SQLData\') | |
('OverrideLogDir', NULL), -- Optional: override log directory (e.g. 'E:\SQLLogs\') | |
('LogInitialSizeMB', 512), -- Initial log file size in MB | |
('LogGrowthMB', 512), -- Log file growth increment in MB | |
('EnableSparseFile', 1), -- 1 = enable sparse file pre-fill, 0 = disable | |
('ReservedLogDriveSpaceMB', NULL), -- MB to leave free on log drive (see docs above) | |
--('ReservedLogDriveSpaceMB', 0), -- π² π² π² DANGER - ARE YOU SURE?! 0 MB to leave free on log drive (see docs above) π² | |
('UseMeaningfulSparseFileName', 1), -- 1 = timestamp in sparse file name, 0 = generic name | |
('BatchSize', 50000), -- Rows per batch insert (log fill speed) | |
('BatchCount', 10000), -- Max number of batches to run | |
('MonitorInterval', 10), -- Report progress every N batches | |
('PerformCleanup', 1); -- 1 = run cleanup at end, 0 = skip cleanup | |
-- ============================================= | |
-- Parameter Extraction (assign to variables from #params) | |
-- ============================================= | |
-- Extract user parameters into variables for use throughout the script. | |
DECLARE @OverrideDataDir NVARCHAR(512); | |
DECLARE @OverrideLogDir NVARCHAR(512); | |
DECLARE @LogInitialSizeMB INT; | |
DECLARE @LogGrowthMB INT; | |
DECLARE @EnableSparseFile BIT; | |
DECLARE @ReservedLogDriveSpaceMB BIGINT; | |
DECLARE @UseMeaningfulSparseFileName BIT; | |
DECLARE @BatchSize INT; | |
DECLARE @BatchCount INT; | |
DECLARE @MonitorInterval INT; | |
DECLARE @PerformCleanup BIT; | |
SELECT @OverrideDataDir = CAST(param_value AS NVARCHAR(512)) FROM #params WHERE param_name = 'OverrideDataDir'; | |
SELECT @OverrideLogDir = CAST(param_value AS NVARCHAR(512)) FROM #params WHERE param_name = 'OverrideLogDir'; | |
SELECT @LogInitialSizeMB = CAST(param_value AS INT) FROM #params WHERE param_name = 'LogInitialSizeMB'; | |
SELECT @LogGrowthMB = CAST(param_value AS INT) FROM #params WHERE param_name = 'LogGrowthMB'; | |
SELECT @EnableSparseFile = CAST(param_value AS BIT) FROM #params WHERE param_name = 'EnableSparseFile'; | |
SELECT @ReservedLogDriveSpaceMB = CAST(param_value AS BIGINT) FROM #params WHERE param_name = 'ReservedLogDriveSpaceMB'; | |
SELECT @UseMeaningfulSparseFileName = CAST(param_value AS BIT) FROM #params WHERE param_name = 'UseMeaningfulSparseFileName'; | |
SELECT @BatchSize = CAST(param_value AS INT) FROM #params WHERE param_name = 'BatchSize'; | |
SELECT @BatchCount = CAST(param_value AS INT) FROM #params WHERE param_name = 'BatchCount'; | |
SELECT @MonitorInterval = CAST(param_value AS INT) FROM #params WHERE param_name = 'MonitorInterval'; | |
SELECT @PerformCleanup = CAST(param_value AS BIT) FROM #params WHERE param_name = 'PerformCleanup'; | |
-- Use these variables throughout the script and pass them as parameters to procedures | |
-- No function-based parameter access, no database prefixes | |
USE master; | |
-- ============================================= | |
-- Variable Declarations and Initialization (internal/derived) | |
-- ============================================= | |
-- These variables are used for dynamic paths, file sizes, and cleanup. πΎ | |
DECLARE @DefaultDataPath NVARCHAR(512); -- Path to a user DB data file (for default dir detection). | |
DECLARE @DefaultLogPath NVARCHAR(512); -- Path to a user DB log file (for default dir detection). | |
DECLARE @DataDir NVARCHAR(512); -- Final data directory used for test DB. | |
DECLARE @LogDir NVARCHAR(512) = NULL; -- Final log directory used for test DB and cleanup (always in scope). | |
DECLARE @DataFile NVARCHAR(512); -- Full path for test DB data file. | |
DECLARE @LogFile NVARCHAR(512); -- Full path for test DB log file. | |
DECLARE @SQL NVARCHAR(MAX); -- For dynamic SQL (DB creation, etc.). | |
DECLARE @SparseFileSizeMB BIGINT = NULL; -- Size of sparse file to pre-fill log drive. | |
DECLARE @LogDriveLetter CHAR(1) = NULL; -- Drive letter for log file. | |
DECLARE @LogDriveFreeMB BIGINT = NULL; -- Free space on log drive (MB). | |
DECLARE @TimeStamp VARCHAR(20) = ''; -- Timestamp for unique sparse file names. | |
DECLARE @SparseFilePath NVARCHAR(512) = NULL; -- Full path for sparse file. | |
DECLARE @CalculatedBufferMB BIGINT = NULL; -- Calculated buffer space to leave free. | |
DECLARE @FinalFreeMB BIGINT = NULL; -- Final free space after log fill (MB). | |
DECLARE @cmd NVARCHAR(1000) = NULL; -- For cleanup PowerShell command (always in scope). | |
-- ============================================= | |
-- Dynamic Data/Log Directory Detection | |
-- ============================================= | |
-- Find default data/log directories from an existing user DB. π | |
SELECT TOP 1 @DefaultDataPath = physical_name FROM sys.master_files WHERE database_id > 4 AND file_id = 1; -- user DB data file | |
SELECT TOP 1 @DefaultLogPath = physical_name FROM sys.master_files WHERE database_id > 4 AND file_id = 2; -- user DB log file | |
-- Extract directory (everything up to the last backslash). | |
SET @DataDir = LEFT(@DefaultDataPath, LEN(@DefaultDataPath) - CHARINDEX('\', REVERSE(@DefaultDataPath)) + 1); | |
SET @LogDir = LEFT(@DefaultLogPath, LEN(@DefaultLogPath) - CHARINDEX('\', REVERSE(@DefaultLogPath)) + 1); | |
-- Allow override from user-tunable parameters. | |
SET @DataDir = ISNULL(@OverrideDataDir, @DataDir); | |
SET @LogDir = ISNULL(@OverrideLogDir, @LogDir); | |
PRINT 'Using directories:'; | |
PRINT ' Data: ' + @DataDir; | |
PRINT ' Log: ' + @LogDir; | |
-- ============================================= | |
-- Ensure xp_cmdshell is enabled before any usage | |
-- ============================================= | |
-- xp_cmdshell is required for PowerShell-based sparse file creation and cleanup. | |
EXEC dbo.SetXpCmdShellEnabled @Enable = 1; | |
-- ============================================= | |
-- Clean up any existing test database | |
-- ============================================= | |
PRINT 'Cleaning up any existing test database...'; | |
IF DB_ID(N'TestLogFill') IS NOT NULL | |
BEGIN | |
PRINT ' Dropping existing TestLogFill database...'; | |
ALTER DATABASE TestLogFill SET SINGLE_USER WITH ROLLBACK IMMEDIATE; | |
DROP DATABASE TestLogFill; | |
END | |
-- ============================================= | |
-- Create Test Database | |
-- ============================================= | |
-- Build file paths for new test DB. | |
SET @DataFile = @DataDir + 'TestLogFill_Data.mdf'; | |
SET @LogFile = @LogDir + 'TestLogFill_Log.ldf'; | |
IF DB_ID(N'TestLogFill') IS NULL | |
BEGIN | |
PRINT 'Creating TestLogFill database...'; | |
SET @SQL = N'CREATE DATABASE TestLogFill | |
ON PRIMARY | |
( | |
NAME = N''TestLogFill_Data'', | |
FILENAME = N''' + @DataFile + ''', | |
SIZE = 100MB | |
) | |
LOG ON | |
( | |
NAME = N''TestLogFill_Log'', | |
FILENAME = N''' + @LogFile + ''', | |
SIZE = ' + CAST(@LogInitialSizeMB AS VARCHAR) + 'MB, | |
FILEGROWTH = ' + CAST(@LogGrowthMB AS VARCHAR) + 'MB | |
);'; | |
EXEC sp_executesql @SQL; | |
PRINT ' Database created successfully.'; | |
END | |
ELSE | |
BEGIN | |
PRINT 'TestLogFill database already exists.'; | |
END | |
-- ============================================= | |
-- Create Test Table and Execute Log Fill (only if DB exists) | |
-- ============================================= | |
IF DB_ID(N'TestLogFill') IS NOT NULL | |
BEGIN | |
-- Create Test Table using dynamic SQL to ensure context | |
SET @SQL = N' | |
USE [TestLogFill]; | |
IF OBJECT_ID(''dbo.LogFill'', ''U'') IS NOT NULL DROP TABLE dbo.LogFill; | |
CREATE TABLE dbo.LogFill | |
( | |
ID INT IDENTITY(1,1) PRIMARY KEY, | |
Dummy CHAR(8000) NOT NULL DEFAULT REPLICATE(''A'', 8000) | |
); | |
'; | |
EXEC sp_executesql @SQL; | |
END | |
ELSE | |
BEGIN | |
PRINT 'ERROR: TestLogFill database does not exist. Aborting table creation and log fill.'; | |
RETURN; | |
END | |
-- ============================================= | |
-- PRE-FILL DRIVE WITH SPARSE FILE (OPTIONAL) | |
-- ============================================= | |
-- Optionally pre-fill the log drive with a sparse file to simulate low disk. | |
USE master; | |
IF @EnableSparseFile = 1 | |
BEGIN | |
-- Get log directory and drive letter for sparse file creation. | |
SELECT @LogDir = LEFT(physical_name, LEN(physical_name) - CHARINDEX('\', REVERSE(physical_name)) + 1) | |
FROM sys.master_files | |
WHERE database_id = DB_ID('TestLogFill') AND file_id = 2; | |
SET @LogDriveLetter = LEFT(@LogDir, 1); | |
-- Get free space on log drive. | |
CREATE TABLE #DriveSpace (Drive CHAR(1), FreeMB BIGINT); | |
INSERT INTO #DriveSpace EXEC master.dbo.xp_fixeddrives; | |
SELECT @LogDriveFreeMB = FreeMB FROM #DriveSpace WHERE Drive = @LogDriveLetter; | |
DROP TABLE #DriveSpace; | |
-- Calculate buffer and sparse file size. | |
SET @CalculatedBufferMB = CASE | |
WHEN @LogDriveFreeMB * 0.02 < 512 THEN 512 | |
ELSE CAST(@LogDriveFreeMB * 0.02 AS BIGINT) | |
END; | |
SET @ReservedLogDriveSpaceMB = ISNULL(@ReservedLogDriveSpaceMB, @CalculatedBufferMB); | |
SET @SparseFileSizeMB = @LogDriveFreeMB - @ReservedLogDriveSpaceMB; | |
-- Build timestamped sparse file name if requested. | |
IF @UseMeaningfulSparseFileName = 1 | |
BEGIN | |
SET @TimeStamp = '_' + | |
REPLACE(CONVERT(VARCHAR(10), GETDATE(), 120), '-', '') + '_' + | |
REPLACE(CONVERT(VARCHAR(8), GETDATE(), 108), ':', ''); | |
END | |
IF @SparseFileSizeMB > 0 | |
BEGIN | |
SET @SparseFilePath = @LogDir + 'TestLogFill_LogDriveFiller' + @TimeStamp + '.sparse'; | |
PRINT ' Log drive ' + @LogDriveLetter + ': has ' + CAST(@LogDriveFreeMB AS VARCHAR) + ' MB free'; | |
PRINT ' Creating sparse file: ' + @SparseFilePath; | |
PRINT ' Sparse file size: ' + CAST(@SparseFileSizeMB AS VARCHAR) + ' MB (98% of free space)'; | |
PRINT ' Buffer space left: ' + CAST(@ReservedLogDriveSpaceMB AS VARCHAR) + ' MB (' + | |
CASE WHEN @ReservedLogDriveSpaceMB = @CalculatedBufferMB | |
THEN 'calculated as 2% of free space or 512 MB minimum' | |
ELSE 'user override' END + ')'; | |
-- Build and execute PowerShell command to create sparse file. | |
DECLARE @PowerShellCmd NVARCHAR(4000) = | |
'powershell -command "fsutil file createnew ''' + @SparseFilePath + ''' ' + CAST(CAST(@SparseFileSizeMB AS BIGINT) * 1024 * 1024 AS VARCHAR) + '; fsutil sparse setflag ''' + @SparseFilePath + '''"'; | |
PRINT ' Executing sparse file creation...'; | |
EXEC xp_cmdshell @PowerShellCmd; | |
PRINT ' Updated drive space after sparse file creation:'; | |
EXEC master.dbo.xp_fixeddrives; | |
END | |
ELSE | |
BEGIN | |
PRINT 'WARNING: Not enough free space to create sparse file! Buffer (' + | |
CAST(@ReservedLogDriveSpaceMB AS VARCHAR) + ' MB) is larger than available space (' + | |
CAST(@LogDriveFreeMB AS VARCHAR) + ' MB)'; | |
END | |
END | |
-- ============================================= | |
-- Main Log Fill Loop (after sparse file creation) | |
-- ============================================= | |
-- This is the main high-speed log fill. Progress and free space are checked | |
-- every @MonitorInterval batches. If free space drops below 10 MB, the loop | |
-- exits with a warning. π₯ | |
IF DB_ID(N'TestLogFill') IS NOT NULL | |
BEGIN | |
-- Inline log fill logic (replaces FillLogFast procedure) | |
SET @SQL = N' | |
USE TestLogFill; | |
DECLARE @i INT = 0; | |
DECLARE @StartTime DATETIME = GETDATE(); | |
DECLARE @StartTimeStr VARCHAR(20) = CONVERT(VARCHAR(20), @StartTime); | |
RAISERROR(''Starting high-speed log fill at %s...'', 0, 1, @StartTimeStr) WITH NOWAIT; | |
BEGIN TRANSACTION; | |
WHILE @i < ' + CAST(@BatchCount AS VARCHAR) + ' | |
BEGIN | |
INSERT INTO dbo.LogFill (Dummy) | |
SELECT TOP (' + CAST(@BatchSize AS VARCHAR) + ') REPLICATE(CHAR(65 + (@i % 26)), 8000) | |
FROM sys.all_objects a CROSS JOIN sys.all_objects b; | |
SET @i = @i + 1; | |
IF @i % ' + CAST(@MonitorInterval AS VARCHAR) + ' = 0 | |
BEGIN | |
DECLARE @ElapsedSec INT = DATEDIFF(SECOND, @StartTime, GETDATE()); | |
DECLARE @RowsInserted BIGINT = @i * ' + CAST(@BatchSize AS VARCHAR) + '; | |
DECLARE @RowsPerSec BIGINT = CASE WHEN @ElapsedSec > 0 THEN @RowsInserted / @ElapsedSec ELSE 0 END; | |
-- Check free space | |
CREATE TABLE #DriveSpace (Drive CHAR(1), FreeMB BIGINT); | |
INSERT INTO #DriveSpace EXEC master.dbo.xp_fixeddrives; | |
DECLARE @CurrentFreeMB BIGINT; | |
SELECT @CurrentFreeMB = FreeMB FROM #DriveSpace WHERE Drive = ''' + @LogDriveLetter + '''; | |
DROP TABLE #DriveSpace; | |
RAISERROR(''Batch %I64d complete. Inserted %I64d rows (%I64d rows/sec). Free space: %I64d MB'', 0, 1, @i, @RowsInserted, @RowsPerSec, @CurrentFreeMB) WITH NOWAIT; | |
IF @CurrentFreeMB < 10 | |
BEGIN | |
RAISERROR(''WARNING: Free space below 10 MB (actual: %I64d MB), stopping log fill.'', 0, 1, @CurrentFreeMB) WITH NOWAIT; | |
BREAK; | |
END | |
CHECKPOINT; | |
END | |
END; | |
IF @@TRANCOUNT > 0 | |
ROLLBACK TRANSACTION; | |
'; | |
EXEC sp_executesql @SQL; | |
END | |
ELSE | |
BEGIN | |
PRINT 'ERROR: TestLogFill database does not exist. Aborting log fill.'; | |
RETURN; | |
END | |
-- ============================================= | |
-- FILL REMAINING DRIVE SPACE | |
-- ============================================= | |
-- If sparse file was used, fill the remaining buffer space with log data. | |
IF @EnableSparseFile = 1 AND @SparseFileSizeMB > 0 | |
BEGIN | |
PRINT 'Filling remaining drive space (' + CAST(@ReservedLogDriveSpaceMB AS VARCHAR) + ' MB) with log data...'; | |
DECLARE @EstimatedRowsPerMB INT = 125; -- Approx. 8000 bytes per row / 1024^2 = ~125 rows/MB | |
DECLARE @MaxRows INT = @ReservedLogDriveSpaceMB * @EstimatedRowsPerMB; | |
DECLARE @AdjustedBatchCount INT = CEILING(CAST(@MaxRows AS FLOAT) / @BatchSize); | |
PRINT ' Estimated rows to fill ' + CAST(@ReservedLogDriveSpaceMB AS VARCHAR) + ' MB: ' + CAST(@MaxRows AS VARCHAR); | |
PRINT ' Adjusted batch count: ' + CAST(@AdjustedBatchCount AS VARCHAR); | |
-- Inline log fill logic for remaining drive space | |
SET @SQL = N' | |
USE TestLogFill; | |
DECLARE @i2 INT = 0; | |
DECLARE @StartTime2 DATETIME = GETDATE(); | |
DECLARE @StartTimeStr2 VARCHAR(20) = CONVERT(VARCHAR(20), @StartTime2); | |
RAISERROR(''Starting high-speed log fill for remaining space at %s...'', 0, 1, @StartTimeStr2) WITH NOWAIT; | |
BEGIN TRANSACTION; | |
WHILE @i2 < ' + CAST(@AdjustedBatchCount AS VARCHAR) + ' | |
BEGIN | |
INSERT INTO dbo.LogFill (Dummy) | |
SELECT TOP (' + CAST(@BatchSize AS VARCHAR) + ') REPLICATE(CHAR(65 + (@i2 % 26)), 8000) | |
FROM sys.all_objects a CROSS JOIN sys.all_objects b; | |
SET @i2 = @i2 + 1; | |
IF @i2 % ' + CAST(@MonitorInterval AS VARCHAR) + ' = 0 | |
BEGIN | |
DECLARE @ElapsedSec2 INT = DATEDIFF(SECOND, @StartTime2, GETDATE()); | |
DECLARE @RowsInserted2 BIGINT = @i2 * ' + CAST(@BatchSize AS VARCHAR) + '; | |
DECLARE @RowsPerSec2 BIGINT = CASE WHEN @ElapsedSec2 > 0 THEN @RowsInserted2 / @ElapsedSec2 ELSE 0 END; | |
-- Check free space | |
CREATE TABLE #DriveSpace2 (Drive CHAR(1), FreeMB BIGINT); | |
INSERT INTO #DriveSpace2 EXEC master.dbo.xp_fixeddrives; | |
DECLARE @CurrentFreeMB2 BIGINT; | |
SELECT @CurrentFreeMB2 = FreeMB FROM #DriveSpace2 WHERE Drive = ''' + @LogDriveLetter + '''; | |
DROP TABLE #DriveSpace2; | |
RAISERROR(''Batch %I64d complete. Inserted %I64d rows (%I64d rows/sec). Free space: %I64d MB'', 0, 1, @i2, @RowsInserted2, @RowsPerSec2, @CurrentFreeMB2) WITH NOWAIT; | |
IF @CurrentFreeMB2 < 10 | |
BEGIN | |
RAISERROR(''WARNING: Free space below 10 MB (actual: %I64d MB), stopping log fill.'', 0, 1, @CurrentFreeMB2) WITH NOWAIT; | |
BREAK; | |
END | |
CHECKPOINT; | |
END | |
END; | |
IF @@TRANCOUNT > 0 | |
ROLLBACK TRANSACTION; | |
'; | |
EXEC sp_executesql @SQL; | |
PRINT ' Final drive space after filling:'; | |
EXEC master.dbo.xp_fixeddrives; | |
CREATE TABLE #FinalDriveSpace (Drive CHAR(1), FreeMB BIGINT); | |
INSERT INTO #FinalDriveSpace EXEC master.dbo.xp_fixeddrives; | |
SELECT @FinalFreeMB = FreeMB FROM #FinalDriveSpace WHERE Drive = @LogDriveLetter; | |
DROP TABLE #FinalDriveSpace; | |
IF @FinalFreeMB < 100 | |
BEGIN | |
PRINT 'WARNING: Drive ' + @LogDriveLetter + ': has only ' + CAST(@FinalFreeMB AS VARCHAR) + ' MB free. Disk is nearly full!'; | |
END | |
ELSE | |
BEGIN | |
PRINT 'Remaining space filled. Drive ' + @LogDriveLetter + ': has ' + CAST(@FinalFreeMB AS VARCHAR) + ' MB free.'; | |
END | |
END | |
ELSE | |
BEGIN | |
PRINT 'Skipping remaining drive space fill (sparse file disabled or insufficient space).'; | |
END | |
-- ============================================= | |
-- Cleanup Section (runs if @PerformCleanup = 1) | |
-- ============================================= | |
-- This section will clean up all test artifacts and sparse files if enabled. | |
IF @PerformCleanup = 1 | |
BEGIN | |
USE master; | |
PRINT 'Cleaning up test resources...'; | |
-- End any open transaction before cleanup | |
IF @@TRANCOUNT > 0 | |
ROLLBACK TRANSACTION; | |
-- Remove the sparse file first | |
SELECT @LogDir = LEFT(physical_name, LEN(physical_name) - CHARINDEX('\', REVERSE(physical_name)) + 1) | |
FROM sys.master_files | |
WHERE database_id = DB_ID('TestLogFill') AND file_id = 2; | |
-- Find and delete sparse files with our naming pattern | |
EXEC dbo.SetXpCmdShellEnabled @Enable = 1; | |
SET @cmd = 'powershell -command "& { Remove-Item -Path ''' + @LogDir + 'TestLogFill_LogDriveFiller*.sparse'' -Force }"'; | |
EXEC xp_cmdshell @cmd; | |
-- Drop the test database | |
IF DB_ID(N'TestLogFill') IS NOT NULL | |
BEGIN | |
ALTER DATABASE TestLogFill SET SINGLE_USER WITH ROLLBACK IMMEDIATE; | |
DROP DATABASE TestLogFill; | |
END | |
-- Disable xp_cmdshell if it was enabled | |
EXEC dbo.SetXpCmdShellEnabled @Enable = 0; | |
PRINT 'Cleanup complete.'; | |
END | |
ELSE | |
BEGIN | |
PRINT 'Cleanup skipped. Set @PerformCleanup = 1 to enable.'; | |
END | |
PRINT 'Log fill process has been initiated.'; | |
PRINT 'Monitor system alerts for disk full conditions.'; | |
PRINT 'When testing is complete, uncomment and run the cleanup section at the end of this script.'; | |
/* | |
-- ============================================= | |
-- Standalone Cleanup Section (can be run anytime) | |
-- ============================================= | |
--Uncomment this section and run manually when you want to clean up all test artifacts and sparse files. | |
--This will work even if the main script was interrupted or the log-filling loop was broken. | |
USE master; | |
PRINT 'Cleaning up test resources...'; | |
-- End any open transaction before cleanup | |
IF @@TRANCOUNT > 0 | |
ROLLBACK TRANSACTION; | |
-- Enable xp_cmdshell if needed | |
IF NOT EXISTS (SELECT 1 FROM sys.configurations WHERE name = 'xp_cmdshell' AND value_in_use = 1) | |
BEGIN | |
EXEC sp_configure 'show advanced options', 1; RECONFIGURE; | |
EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE; | |
END | |
-- Recalculate log directory from TestLogFill if it exists, else use default from any user DB | |
DECLARE @LogDir NVARCHAR(512); | |
SELECT TOP 1 @LogDir = LEFT(physical_name, LEN(physical_name) - CHARINDEX('\', REVERSE(physical_name)) + 1) | |
FROM sys.master_files | |
WHERE (database_id = DB_ID('TestLogFill') AND file_id = 2) | |
OR (database_id > 4 AND file_id = 2); | |
-- Remove sparse files matching the pattern | |
DECLARE @cmd NVARCHAR(1000); | |
SET @cmd = 'powershell -command "& { Remove-Item -Path ''' + @LogDir + 'TestLogFill_LogDriveFiller*.sparse'' -Force -ErrorAction SilentlyContinue }"'; | |
EXEC xp_cmdshell @cmd; | |
-- Drop the test database if it exists | |
IF DB_ID(N'TestLogFill') IS NOT NULL | |
BEGIN | |
ALTER DATABASE TestLogFill SET SINGLE_USER WITH ROLLBACK IMMEDIATE; | |
DROP DATABASE TestLogFill; | |
END | |
-- Disable xp_cmdshell and advanced options after cleanup | |
EXEC sp_configure 'xp_cmdshell', 0; RECONFIGURE; | |
EXEC sp_configure 'show advanced options', 0; RECONFIGURE; | |
PRINT 'Cleanup complete.'; | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment