From a6fc2adff6d65534776495bdb5e8ca497c22ab8d Mon Sep 17 00:00:00 2001 From: ekins Date: Mon, 30 Dec 2024 13:27:15 -0600 Subject: [PATCH 01/13] Initial RDS Code changes added --- AmazonRDSBackupHelp.md | 1 + CommandExecute.sql | 64 +++- DatabaseBackup.sql | 299 ++++++++++++------ MaintenanceSolution.sql | 658 ++++++++++++++++++++++++++++++++++------ RDS_BackupLog.sql | 32 ++ README.md | 30 +- 6 files changed, 884 insertions(+), 200 deletions(-) create mode 100644 AmazonRDSBackupHelp.md create mode 100644 RDS_BackupLog.sql diff --git a/AmazonRDSBackupHelp.md b/AmazonRDSBackupHelp.md new file mode 100644 index 0000000..3e44861 --- /dev/null +++ b/AmazonRDSBackupHelp.md @@ -0,0 +1 @@ +** Link to Launch Blog will replace this ** \ No newline at end of file diff --git a/CommandExecute.sql b/CommandExecute.sql index 81dad9b..4581426 100644 --- a/CommandExecute.sql +++ b/CommandExecute.sql @@ -37,6 +37,9 @@ BEGIN --// License: https://ola.hallengren.com/license.html //-- --// GitHub: https://github.com/olahallengren/sql-server-maintenance-solution //-- --// Version: 2024-12-27 18:10:28 //-- + --// //-- + --// Forked Changes https://github.com/amazon-contributing/aws-sql-server-maintenance-solution //-- + --// Version: 2024-12-30 12:58 //-- ---------------------------------------------------------------------------------------------------- SET NOCOUNT ON @@ -70,6 +73,28 @@ BEGIN DECLARE @RevertCommand nvarchar(max) + ---------------------------------------------------------------------------------------------------- + --// Original Copyright 2024 Ola Hallengren. Licensed under the MIT License. //-- + --// Modifications Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. //-- + DECLARE @AmazonRDS bit = CASE WHEN DB_ID('rdsadmin') IS NOT NULL AND SUSER_SNAME(0x01) = 'rdsa' THEN 1 ELSE 0 END + DECLARE @task_id INT + + DECLARE @RDSQueue TABLE ([task_id] INT, + [task_type] nvarchar(max), + [database_name] nvarchar(max), + [% complete] nvarchar(max), + [duration (mins)] nvarchar(max), + [lifecycle] nvarchar(max), + [task_info] nvarchar(max), + [last_updated] nvarchar(max), + [created_at] nvarchar(max), + [S3_object_arn] nvarchar(max), + [overwrite_s3_backup_file] nvarchar(max), + [KMS_master_key_arn] nvarchar(max), + [filepath] nvarchar(max), + [overwrite_file] BIT) + ---------------------------------------------------------------------------------------------------- + ---------------------------------------------------------------------------------------------------- --// Check core requirements //-- ---------------------------------------------------------------------------------------------------- @@ -224,9 +249,41 @@ BEGIN IF @Mode = 1 AND @Execute = 'Y' BEGIN - EXECUTE @sp_executesql @stmt = @Command - SET @Error = @@ERROR - SET @ReturnCode = @Error + ---------------------------------------------------------------------------------------------------- + --// Original Copyright 2024 Ola Hallengren. Licensed under the MIT License. //-- + --// Modifications Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. //-- + IF @AmazonRDS = 1 + BEGIN + BEGIN TRY + EXECUTE @sp_executesql @stmt = @Command + INSERT INTO @RDSQueue exec msdb..rds_task_status @db_name=@DatabaseName; + SELECT TOP 1 @task_id=task_id from @RDSQueue ORDER BY task_id DESC + INSERT INTO dbo.RDS_BackupLog (ID, task_id, [Status]) VALUES (@ID, @task_id, 'CREATED') + END TRY + BEGIN CATCH + SET @Error = ERROR_NUMBER() + SET @ErrorMessageOriginal = ERROR_MESSAGE() + BEGIN + SET @ErrorMessage = 'RDS:Msg ' + CAST(ERROR_NUMBER() AS nvarchar) + ', ' + ISNULL(ERROR_MESSAGE(),'') + + SET @Severity = CASE WHEN ERROR_NUMBER() IN(1205,1222) THEN @LockMessageSeverity ELSE 16 END + IF @ErrorMessageOriginal NOT LIKE 'A task has already been issued for database: %' + RAISERROR('%s',@Severity,1,@ErrorMessage) WITH LOG + ELSE + BEGIN + SET @ErrorMessage = 'RDS:Msg ' + CAST(ERROR_NUMBER() AS nvarchar) + ', ' + ISNULL(ERROR_MESSAGE(),'') + RAISERROR('%s',@Severity,1,@ErrorMessage) WITH NOWAIT + END + END + END CATCH + END + ELSE + BEGIN + EXECUTE @sp_executesql @stmt = @Command + SET @Error = @@ERROR + SET @ReturnCode = @Error + END + ---------------------------------------------------------------------------------------------------- END IF @Mode = 2 AND @Execute = 'Y' @@ -290,4 +347,3 @@ BEGIN END GO - diff --git a/DatabaseBackup.sql b/DatabaseBackup.sql index 4badbc0..68c8ad1 100644 --- a/DatabaseBackup.sql +++ b/DatabaseBackup.sql @@ -74,6 +74,14 @@ ALTER PROCEDURE [dbo].[DatabaseBackup] @StringDelimiter nvarchar(max) = ',', @DatabaseOrder nvarchar(max) = NULL, @DatabasesInParallel nvarchar(max) = 'N', + + ---------------------------------------------------------------------------------------------------- + --// Original Copyright 2024 Ola Hallengren. Licensed under the MIT License. //-- + --// Modifications Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. //-- +@S3BucketArn nvarchar(255) = NULL, +@kms_master_key_arn nvarchar(max) = NULL, + ---------------------------------------------------------------------------------------------------- + @LogToTable nvarchar(max) = 'N', @Execute nvarchar(max) = 'Y' @@ -86,6 +94,8 @@ BEGIN --// License: https://ola.hallengren.com/license.html //-- --// GitHub: https://github.com/olahallengren/sql-server-maintenance-solution //-- --// Version: 2024-12-27 18:10:28 //-- + --// //-- + --// Modifications Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. //-- ---------------------------------------------------------------------------------------------------- SET NOCOUNT ON @@ -150,6 +160,7 @@ BEGIN DECLARE @CurrentDate datetime2 DECLARE @CurrentDateUTC datetime2 DECLARE @CurrentCleanupDate datetime2 + DECLARE @CurrentReplicaID uniqueidentifier DECLARE @CurrentAvailabilityGroupID uniqueidentifier DECLARE @CurrentAvailabilityGroup nvarchar(max) @@ -261,6 +272,15 @@ BEGIN DECLARE @Version numeric(18,10) = CAST(LEFT(CAST(SERVERPROPERTY('ProductVersion') AS nvarchar(max)),CHARINDEX('.',CAST(SERVERPROPERTY('ProductVersion') AS nvarchar(max))) - 1) + '.' + REPLACE(RIGHT(CAST(SERVERPROPERTY('ProductVersion') AS nvarchar(max)), LEN(CAST(SERVERPROPERTY('ProductVersion') AS nvarchar(max))) - CHARINDEX('.',CAST(SERVERPROPERTY('ProductVersion') AS nvarchar(max)))),'.','') AS numeric(18,10)) + ---------------------------------------------------------------------------------------------------- + --// Original Copyright 2024 Ola Hallengren. Licensed under the MIT License. //-- + --// Modifications Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. //-- + DECLARE @CurrentRDSBackupType nvarchar(20) + DECLARE @CurrentRDSDatabaseFileName nvarchar(4000) + + DECLARE @ServerName nvarchar(max) = CASE WHEN SERVERPROPERTY('EngineEdition') = 8 THEN LEFT(CAST(SERVERPROPERTY('ServerName') AS nvarchar(max)),CHARINDEX('.',CAST(SERVERPROPERTY('ServerName') AS nvarchar(max))) - 1) ELSE CAST(SERVERPROPERTY('MachineName') AS nvarchar(max)) END + ---------------------------------------------------------------------------------------------------- + IF @Version >= 14 BEGIN SELECT @HostPlatform = host_platform @@ -344,6 +364,13 @@ BEGIN SET @Parameters += ', @LogToTable = ' + ISNULL('''' + REPLACE(@LogToTable,'''','''''') + '''','NULL') SET @Parameters += ', @Execute = ' + ISNULL('''' + REPLACE(@Execute,'''','''''') + '''','NULL') + ---------------------------------------------------------------------------------------------------- + --// Original Copyright 2024 Ola Hallengren. Licensed under the MIT License. //-- + --// Modifications Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. //-- + SET @Parameters += ', @S3BucketArn = ' + ISNULL('''' + REPLACE(@S3BucketArn,'''','''''') + '''','NULL') + SET @Parameters += ', @kms_master_key_arn = ' + ISNULL('''' + REPLACE(@kms_master_key_arn,'''','''''') + '''','NULL') + ---------------------------------------------------------------------------------------------------- + SET @StartMessage = 'Date and time: ' + CONVERT(nvarchar,@StartTime,120) RAISERROR('%s',10,1,@StartMessage) WITH NOWAIT @@ -431,11 +458,30 @@ BEGIN SELECT 'The transaction count is not 0.', 16, 1 END - IF @AmazonRDS = 1 + ---------------------------------------------------------------------------------------------------- + --// Original Copyright 2024 Ola Hallengren. Licensed under the MIT License. //-- + --// Modifications Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. //-- + IF (@AmazonRDS = 1) BEGIN - INSERT INTO @Errors ([Message], Severity, [State]) - SELECT 'The stored procedure DatabaseBackup is not supported on Amazon RDS.', 16, 1 + IF (@AmazonRDS = 1 AND @S3BucketArn IS NULL) OR (@AmazonRDS = 1 AND @S3BucketArn = '') + BEGIN + INSERT INTO @Errors ([Message], Severity, [State]) + SELECT 'The parameter @S3BucketArn is a required for Amazon RDS backups.', 16, 1 + END + + IF (@S3BucketArn NOT LIKE 'arn:aws:s3:%' AND @S3BucketArn != '') + BEGIN + INSERT INTO @Errors ([Message], Severity, [State]) + SELECT 'The parameter @S3BucketArn is invalid.', 16, 1 + END + + IF (@kms_master_key_arn NOT LIKE 'arn:aws:kms:%' AND @kms_master_key_arn != '') + BEGIN + INSERT INTO @Errors ([Message], Severity, [State]) + SELECT 'The parameter @kms_master_key_arn is invalid.', 16, 1 + END END + ---------------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------- --// Select databases //-- @@ -886,14 +932,21 @@ BEGIN BREAK END - INSERT INTO @DirectoryInfo (FileExists, FileIsADirectory, ParentDirectoryExists) - EXECUTE [master].dbo.xp_fileexist @CurrentRootDirectoryPath - - IF NOT EXISTS (SELECT * FROM @DirectoryInfo WHERE FileExists = 0 AND FileIsADirectory = 1 AND ParentDirectoryExists = 1) - BEGIN - INSERT INTO @Errors ([Message], Severity, [State]) - SELECT 'The directory ' + @CurrentRootDirectoryPath + ' does not exist.', 16, 1 - END + ---------------------------------------------------------------------------------------------------- + --// Original Copyright 2024 Ola Hallengren. Licensed under the MIT License. //-- + --// Modifications Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. //-- + IF @AmazonRDS = 0 + BEGIN + INSERT INTO @DirectoryInfo (FileExists, FileIsADirectory, ParentDirectoryExists) + EXECUTE [master].dbo.xp_fileexist @CurrentRootDirectoryPath + + IF NOT EXISTS (SELECT * FROM @DirectoryInfo WHERE FileExists = 0 AND FileIsADirectory = 1 AND ParentDirectoryExists = 1) + BEGIN + INSERT INTO @Errors ([Message], Severity, [State]) + SELECT 'The directory ' + @CurrentRootDirectoryPath + ' does not exist.', 16, 1 + END + END + ---------------------------------------------------------------------------------------------------- UPDATE @Directories SET Completed = 1 @@ -1137,7 +1190,11 @@ BEGIN IF @CleanupTime IS NOT NULL AND @URL IS NOT NULL BEGIN INSERT INTO @Errors ([Message], Severity, [State]) - SELECT 'The value for the parameter @CleanupTime is not supported. Cleanup is not supported on Azure Blob Storage.', 16, 2 + ---------------------------------------------------------------------------------------------------- + --// Original Copyright 2024 Ola Hallengren. Licensed under the MIT License. //-- + --// Modifications Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. //-- + SELECT 'The value for the parameter @CleanupTime is not supported. Cleanup is not supported on Amazon S3 or Azure Blob Storage.', 16, 2 + ---------------------------------------------------------------------------------------------------- END IF @CleanupTime IS NOT NULL AND EXISTS(SELECT * FROM @Directories WHERE DirectoryPath = 'NUL') @@ -1432,6 +1489,16 @@ BEGIN SELECT 'The value for the parameter @NumberOfFiles is not supported. The maximum number of files when performing mirrored backups to S3 storage is 32.', 16, 10 END + ---------------------------------------------------------------------------------------------------- + --// Original Copyright 2024 Ola Hallengren. Licensed under the MIT License. //-- + --// Modifications Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. //-- + IF @NumberOfFiles > 10 AND @AmazonRDS = 1 + BEGIN + INSERT INTO @Errors ([Message], Severity, [State]) + SELECT 'The value for the parameter @NumberOfFiles is not supported. The maximum number of files when performing Amazon RDS backups is 10.', 16, 10 + END + ---------------------------------------------------------------------------------------------------- + ---------------------------------------------------------------------------------------------------- IF @MinBackupSizeForMultipleFiles <= 0 @@ -2796,15 +2863,22 @@ BEGIN FROM sys.database_mirroring WHERE database_id = DB_ID(@CurrentDatabaseName) - IF EXISTS (SELECT * FROM msdb.dbo.log_shipping_primary_databases WHERE primary_database = @CurrentDatabaseName) - BEGIN - SET @CurrentLogShippingRole = 'PRIMARY' - END - ELSE - IF EXISTS (SELECT * FROM msdb.dbo.log_shipping_secondary_databases WHERE secondary_database = @CurrentDatabaseName) + ---------------------------------------------------------------------------------------------------- + --// Original Copyright 2024 Ola Hallengren. Licensed under the MIT License. //-- + --// Modifications Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. //-- + IF @AmazonRDS = 0 BEGIN - SET @CurrentLogShippingRole = 'SECONDARY' - END + IF EXISTS (SELECT * FROM msdb.dbo.log_shipping_primary_databases WHERE primary_database = @CurrentDatabaseName) + BEGIN + SET @CurrentLogShippingRole = 'PRIMARY' + END + ELSE + IF EXISTS (SELECT * FROM msdb.dbo.log_shipping_secondary_databases WHERE secondary_database = @CurrentDatabaseName) + BEGIN + SET @CurrentLogShippingRole = 'SECONDARY' + END + END + ---------------------------------------------------------------------------------------------------- IF @CurrentAvailabilityGroup IS NOT NULL BEGIN @@ -3405,6 +3479,13 @@ BEGIN -- Create directory IF @HostPlatform = 'Windows' AND (@BackupSoftware <> 'DATA_DOMAIN_BOOST' OR @BackupSoftware IS NULL) + + ---------------------------------------------------------------------------------------------------- + --// Original Copyright 2024 Ola Hallengren. Licensed under the MIT License. //-- + --// Modifications Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. //-- + AND (@AmazonRDS = 0) + ---------------------------------------------------------------------------------------------------- + AND NOT EXISTS(SELECT * FROM @CurrentDirectories WHERE DirectoryPath = 'NUL' OR DirectoryPath IN(SELECT DirectoryPath FROM @Directories)) BEGIN WHILE (1 = 1) @@ -3558,76 +3639,110 @@ BEGIN -- Perform a backup IF NOT EXISTS (SELECT * FROM @CurrentDirectories WHERE DirectoryPath <> 'NUL' AND DirectoryPath NOT IN(SELECT DirectoryPath FROM @Directories) AND (CreateOutput <> 0 OR CreateOutput IS NULL)) - OR @HostPlatform = 'Linux' + ---------------------------------------------------------------------------------------------------- + --// Original Copyright 2024 Ola Hallengren. Licensed under the MIT License. //-- + --// Modifications Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. //-- + OR @HostPlatform = 'Linux' OR @AmazonRDS = 1 BEGIN IF @BackupSoftware IS NULL - BEGIN - SET @CurrentDatabaseContext = 'master' - - SELECT @CurrentCommandType = CASE - WHEN @CurrentBackupType IN('DIFF','FULL') THEN 'BACKUP_DATABASE' - WHEN @CurrentBackupType = 'LOG' THEN 'BACKUP_LOG' - END - - SELECT @CurrentCommand = CASE - WHEN @CurrentBackupType IN('DIFF','FULL') THEN 'BACKUP DATABASE ' + QUOTENAME(@CurrentDatabaseName) - WHEN @CurrentBackupType = 'LOG' THEN 'BACKUP LOG ' + QUOTENAME(@CurrentDatabaseName) - END - - IF @ReadWriteFileGroups = 'Y' AND @CurrentDatabaseName <> 'master' SET @CurrentCommand += ' READ_WRITE_FILEGROUPS' - - SET @CurrentCommand += ' TO' - - SELECT @CurrentCommand += ' ' + [Type] + ' = N''' + REPLACE(FilePath,'''','''''') + '''' + CASE WHEN ROW_NUMBER() OVER (ORDER BY FilePath ASC) <> @CurrentNumberOfFiles THEN ',' ELSE '' END - FROM @CurrentFiles - WHERE Mirror = 0 - ORDER BY FilePath ASC - - IF EXISTS(SELECT * FROM @CurrentFiles WHERE Mirror = 1) - BEGIN - SET @CurrentCommand += ' MIRROR TO' - - SELECT @CurrentCommand += ' ' + [Type] + ' = N''' + REPLACE(FilePath,'''','''''') + '''' + CASE WHEN ROW_NUMBER() OVER (ORDER BY FilePath ASC) <> @CurrentNumberOfFiles THEN ',' ELSE '' END - FROM @CurrentFiles - WHERE Mirror = 1 - ORDER BY FilePath ASC - END - - SET @CurrentCommand += ' WITH ' - IF @CheckSum = 'Y' SET @CurrentCommand += 'CHECKSUM' - IF @CheckSum = 'N' SET @CurrentCommand += 'NO_CHECKSUM' - IF @Version >= 10 - BEGIN - SET @CurrentCommand += CASE WHEN @Compress = 'Y' AND (@CurrentIsEncrypted = 0 OR (@CurrentIsEncrypted = 1 AND ((@Version >= 13 AND @CurrentMaxTransferSize >= 65537) OR @Version >= 15.0404316 OR SERVERPROPERTY('EngineEdition') = 8))) THEN ', COMPRESSION' ELSE ', NO_COMPRESSION' END - END - - IF @Compress = 'Y' AND @CompressionAlgorithm IS NOT NULL - BEGIN - SET @CurrentCommand += ' (ALGORITHM = ' + @CompressionAlgorithm + ')' - END - - IF @CurrentBackupType = 'DIFF' SET @CurrentCommand += ', DIFFERENTIAL' - - IF EXISTS(SELECT * FROM @CurrentFiles WHERE Mirror = 1) - BEGIN - SET @CurrentCommand += ', FORMAT' - END - - IF @CopyOnly = 'Y' SET @CurrentCommand += ', COPY_ONLY' - IF @NoRecovery = 'Y' AND @CurrentBackupType = 'LOG' SET @CurrentCommand += ', NORECOVERY' - IF @Init = 'Y' SET @CurrentCommand += ', INIT' - IF @Format = 'Y' SET @CurrentCommand += ', FORMAT' - IF @BlockSize IS NOT NULL SET @CurrentCommand += ', BLOCKSIZE = ' + CAST(@BlockSize AS nvarchar) - IF @BufferCount IS NOT NULL SET @CurrentCommand += ', BUFFERCOUNT = ' + CAST(@BufferCount AS nvarchar) - IF @CurrentMaxTransferSize IS NOT NULL SET @CurrentCommand += ', MAXTRANSFERSIZE = ' + CAST(@CurrentMaxTransferSize AS nvarchar) - IF @Description IS NOT NULL SET @CurrentCommand += ', DESCRIPTION = N''' + REPLACE(@Description,'''','''''') + '''' - IF @BackupOptions IS NOT NULL SET @CurrentCommand += ', BACKUP_OPTIONS = N''' + REPLACE(@BackupOptions,'''','''''') + '''' - IF @Encrypt = 'Y' SET @CurrentCommand += ', ENCRYPTION (ALGORITHM = ' + UPPER(@EncryptionAlgorithm) + ', ' - IF @Encrypt = 'Y' AND @ServerCertificate IS NOT NULL SET @CurrentCommand += 'SERVER CERTIFICATE = ' + QUOTENAME(@ServerCertificate) - IF @Encrypt = 'Y' AND @ServerAsymmetricKey IS NOT NULL SET @CurrentCommand += 'SERVER ASYMMETRIC KEY = ' + QUOTENAME(@ServerAsymmetricKey) - IF @Encrypt = 'Y' SET @CurrentCommand += ')' - IF @URL IS NOT NULL AND @Credential IS NOT NULL SET @CurrentCommand += ', CREDENTIAL = N''' + REPLACE(@Credential,'''','''''') + '''' + BEGIN + IF @AmazonRDS = 1 + BEGIN + SET @CurrentDatabaseContext = 'master' + + SELECT @CurrentCommandType = CASE + WHEN @CurrentBackupType IN('DIFF','FULL') THEN 'BACKUP_DATABASE' + + END + + SELECT @CurrentRDSBackupType = CASE + WHEN @CurrentBackupType = 'DIFF' THEN 'DIFFERENTIAL' + WHEN @CurrentBackupType = 'FULL' THEN 'FULL' + END + + IF @CurrentNumberOfFiles > 10 SET @CurrentNumberOfFiles = 10 + + SET @CurrentDatabaseFileName = @ServerName + '/' + @CurrentDatabaseFileName + + IF @CurrentNumberOfFiles > 1 + SELECT @CurrentDatabaseFileName=REPLACE(@CurrentDatabaseFileName,'_{FileNumber}','*'); + + IF (@kms_master_key_arn IS NULL) + SET @kms_master_key_arn = '' + + SET @CurrentCommand = 'EXEC msdb.dbo.rds_backup_database @source_db_name = ' + QUOTENAME(@CurrentDatabaseName) + ', @s3_arn_to_backup_to = ' + '''' + @S3BucketArn + '/' + @CurrentDatabaseFileName + '''' + ', @kms_master_key_arn = ' + '''' + @kms_master_key_arn + '''' + ', @overwrite_s3_backup_file=1 ' + ', @type=' + '''' + @CurrentRDSBackupType + '''' + ', @number_of_files= ' + CAST(@CurrentNumberOfFiles AS VarChar(2)) + ';' + END + ELSE + ---------------------------------------------------------------------------------------------------- + BEGIN + SET @CurrentDatabaseContext = 'master' + + SELECT @CurrentCommandType = CASE + WHEN @CurrentBackupType IN('DIFF','FULL') THEN 'BACKUP_DATABASE' + WHEN @CurrentBackupType = 'LOG' THEN 'BACKUP_LOG' + END + + SELECT @CurrentCommand = CASE + WHEN @CurrentBackupType IN('DIFF','FULL') THEN 'BACKUP DATABASE ' + QUOTENAME(@CurrentDatabaseName) + WHEN @CurrentBackupType = 'LOG' THEN 'BACKUP LOG ' + QUOTENAME(@CurrentDatabaseName) + END + + IF @ReadWriteFileGroups = 'Y' AND @CurrentDatabaseName <> 'master' SET @CurrentCommand += ' READ_WRITE_FILEGROUPS' + + SET @CurrentCommand += ' TO' + + SELECT @CurrentCommand += ' ' + [Type] + ' = N''' + REPLACE(FilePath,'''','''''') + '''' + CASE WHEN ROW_NUMBER() OVER (ORDER BY FilePath ASC) <> @CurrentNumberOfFiles THEN ',' ELSE '' END + FROM @CurrentFiles + WHERE Mirror = 0 + ORDER BY FilePath ASC + + IF EXISTS(SELECT * FROM @CurrentFiles WHERE Mirror = 1) + BEGIN + SET @CurrentCommand += ' MIRROR TO' + + SELECT @CurrentCommand += ' ' + [Type] + ' = N''' + REPLACE(FilePath,'''','''''') + '''' + CASE WHEN ROW_NUMBER() OVER (ORDER BY FilePath ASC) <> @CurrentNumberOfFiles THEN ',' ELSE '' END + FROM @CurrentFiles + WHERE Mirror = 1 + ORDER BY FilePath ASC + END + + SET @CurrentCommand += ' WITH ' + IF @CheckSum = 'Y' SET @CurrentCommand += 'CHECKSUM' + IF @CheckSum = 'N' SET @CurrentCommand += 'NO_CHECKSUM' + + IF @Version >= 10 + BEGIN + SET @CurrentCommand += CASE WHEN @Compress = 'Y' AND (@CurrentIsEncrypted = 0 OR (@CurrentIsEncrypted = 1 AND ((@Version >= 13 AND @CurrentMaxTransferSize >= 65537) OR @Version >= 15.0404316 OR SERVERPROPERTY('EngineEdition') = 8))) THEN ', COMPRESSION' ELSE ', NO_COMPRESSION' END + END + + IF @Compress = 'Y' AND @CompressionAlgorithm IS NOT NULL + BEGIN + SET @CurrentCommand += ' (ALGORITHM = ' + @CompressionAlgorithm + ')' + END + + IF @CurrentBackupType = 'DIFF' SET @CurrentCommand += ', DIFFERENTIAL' + + IF EXISTS(SELECT * FROM @CurrentFiles WHERE Mirror = 1) + BEGIN + SET @CurrentCommand += ', FORMAT' + END + + IF @CopyOnly = 'Y' SET @CurrentCommand += ', COPY_ONLY' + IF @NoRecovery = 'Y' AND @CurrentBackupType = 'LOG' SET @CurrentCommand += ', NORECOVERY' + IF @Init = 'Y' SET @CurrentCommand += ', INIT' + IF @Format = 'Y' SET @CurrentCommand += ', FORMAT' + IF @BlockSize IS NOT NULL SET @CurrentCommand += ', BLOCKSIZE = ' + CAST(@BlockSize AS nvarchar) + IF @BufferCount IS NOT NULL SET @CurrentCommand += ', BUFFERCOUNT = ' + CAST(@BufferCount AS nvarchar) + IF @CurrentMaxTransferSize IS NOT NULL SET @CurrentCommand += ', MAXTRANSFERSIZE = ' + CAST(@CurrentMaxTransferSize AS nvarchar) + IF @Description IS NOT NULL SET @CurrentCommand += ', DESCRIPTION = N''' + REPLACE(@Description,'''','''''') + '''' + IF @BackupOptions IS NOT NULL SET @CurrentCommand += ', BACKUP_OPTIONS = N''' + REPLACE(@BackupOptions,'''','''''') + '''' + IF @Encrypt = 'Y' SET @CurrentCommand += ', ENCRYPTION (ALGORITHM = ' + UPPER(@EncryptionAlgorithm) + ', ' + IF @Encrypt = 'Y' AND @ServerCertificate IS NOT NULL SET @CurrentCommand += 'SERVER CERTIFICATE = ' + QUOTENAME(@ServerCertificate) + IF @Encrypt = 'Y' AND @ServerAsymmetricKey IS NOT NULL SET @CurrentCommand += 'SERVER ASYMMETRIC KEY = ' + QUOTENAME(@ServerAsymmetricKey) + IF @Encrypt = 'Y' SET @CurrentCommand += ')' + IF @URL IS NOT NULL AND @Credential IS NOT NULL SET @CurrentCommand += ', CREDENTIAL = N''' + REPLACE(@Credential,'''','''''') + '''' + END END IF @BackupSoftware = 'LITESPEED' @@ -3831,7 +3946,11 @@ BEGIN END -- Verify the backup - IF @CurrentBackupOutput = 0 AND @Verify = 'Y' + ---------------------------------------------------------------------------------------------------- + --// Original Copyright 2024 Ola Hallengren. Licensed under the MIT License. //-- + --// Modifications Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. //-- + IF @CurrentBackupOutput = 0 AND @Verify = 'Y' AND @AmazonRDS = 0 + ---------------------------------------------------------------------------------------------------- BEGIN WHILE (1 = 1) BEGIN @@ -4112,6 +4231,7 @@ BEGIN SET @CurrentDate = NULL SET @CurrentDateUTC = NULL SET @CurrentCleanupDate = NULL + SET @CurrentReplicaID = NULL SET @CurrentAvailabilityGroupID = NULL SET @CurrentAvailabilityGroup = NULL @@ -4158,5 +4278,4 @@ BEGIN ---------------------------------------------------------------------------------------------------- END -GO - +GO \ No newline at end of file diff --git a/MaintenanceSolution.sql b/MaintenanceSolution.sql index f68c161..6228bf7 100644 --- a/MaintenanceSolution.sql +++ b/MaintenanceSolution.sql @@ -10,13 +10,21 @@ License: https://ola.hallengren.com/license.html GitHub: https://github.com/olahallengren/sql-server-maintenance-solution -Version: 2024-12-27 18:10:28 +Version: 2024-12-27 18:10:28 You can contact me by e-mail at ola@hallengren.com. Ola Hallengren https://ola.hallengren.com +-- Original Copyright 2024 Ola Hallengren. Licensed under the MIT License. +-- Modifications Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + +Modified to add support for Amazon RDS for SQL Server + +https://github.com/amazon-contributing/aws-sql-server-maintenance-solution +Version: 2024-12-30 12:58 + */ USE [master] -- Specify the database in which the objects will be created. @@ -30,6 +38,13 @@ DECLARE @CleanupTime int = NULL -- Time in hours, after DECLARE @OutputFileDirectory nvarchar(max) = NULL -- Specify the output file directory. If no directory is specified, then the SQL Server error log directory is used. DECLARE @LogToTable nvarchar(max) = 'Y' -- Log commands to a table. + ---------------------------------------------------------------------------------------------------- + --// Original Copyright 2024 Ola Hallengren. Licensed under the MIT License. //-- + --// Modifications Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. //-- +DECLARE @S3BucketArn nvarchar(max) = NULL -- AWS S3 Bucket ARN value. +DECLARE @kms_master_key_arn nvarchar(max) = NULL -- AWS kms master key ARN value. + ---------------------------------------------------------------------------------------------------- + DECLARE @ErrorMessage nvarchar(max) IF IS_SRVROLEMEMBER('sysadmin') = 0 AND NOT (DB_ID('rdsadmin') IS NOT NULL AND SUSER_SNAME(0x01) = 'rdsa') @@ -56,6 +71,16 @@ BEGIN RAISERROR(@ErrorMessage,16,1) WITH NOWAIT END + ---------------------------------------------------------------------------------------------------- + --// Original Copyright 2024 Ola Hallengren. Licensed under the MIT License. //-- + --// Modifications Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. //-- +IF ( DB_NAME() IN('master','rdsadmin') ) AND (DB_ID('rdsadmin') IS NOT NULL AND SUSER_SNAME(0x01) = 'rdsa') +BEGIN + SET @ErrorMessage = 'SQL Server Maintenance Solution cannot be installed in master or rdsadmin database' + RAISERROR(@ErrorMessage,16,1) WITH NOWAIT +END + ---------------------------------------------------------------------------------------------------- + IF OBJECT_ID('tempdb..#Config') IS NOT NULL DROP TABLE #Config CREATE TABLE #Config ([Name] nvarchar(max), @@ -68,6 +93,12 @@ INSERT INTO #Config ([Name], [Value]) VALUES('CleanupTime', @CleanupTime) INSERT INTO #Config ([Name], [Value]) VALUES('OutputFileDirectory', @OutputFileDirectory) INSERT INTO #Config ([Name], [Value]) VALUES('LogToTable', @LogToTable) INSERT INTO #Config ([Name], [Value]) VALUES('DatabaseName', DB_NAME(DB_ID())) + ---------------------------------------------------------------------------------------------------- + --// Original Copyright 2024 Ola Hallengren. Licensed under the MIT License. //-- + --// Modifications Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. //-- +INSERT INTO #Config ([Name], [Value]) VALUES('S3BucketArn', @S3BucketArn) +INSERT INTO #Config ([Name], [Value]) VALUES('kms_master_key_arn', @kms_master_key_arn) + ---------------------------------------------------------------------------------------------------- GO SET ANSI_NULLS ON GO @@ -98,6 +129,80 @@ CREATE TABLE [dbo].[CommandLog]( )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ) END +GO + ---------------------------------------------------------------------------------------------------- + --// Original Copyright 2024 Ola Hallengren. Licensed under the MIT License. //-- + --// Modifications Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. //-- +SET ANSI_NULLS ON +GO +SET QUOTED_IDENTIFIER ON +GO +IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[RDS_BackupLog]') AND type in (N'U')) AND EXISTS(SELECT DB_ID('rdsadmin')) AND SUSER_SNAME(0x01) = 'rdsa' +BEGIN + CREATE TABLE [dbo].[RDS_BackupLog]( + [ID] [int] NOT NULL, + [task_id] [int] NOT NULL, + [Status] [nvarchar](max) NULL, + [task_Info] [nvarchar](max) NULL, + CONSTRAINT [PK_RDS_BackupLog] PRIMARY KEY CLUSTERED + ( [ID] ASC, [task_id] ASC ) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ) +END +GO + +SET ANSI_NULLS ON +GO +SET QUOTED_IDENTIFIER ON +GO +IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Queue]') AND type in (N'U')) +BEGIN +CREATE TABLE [dbo].[Queue]( + [QueueID] [int] IDENTITY(1,1) NOT NULL, + [SchemaName] [sysname] NOT NULL, + [ObjectName] [sysname] NOT NULL, + [Parameters] [nvarchar](max) NOT NULL, + [QueueStartTime] [datetime2](7) NULL, + [SessionID] [smallint] NULL, + [RequestID] [int] NULL, + [RequestStartTime] [datetime] NULL, + CONSTRAINT [PK_Queue] PRIMARY KEY CLUSTERED +( + [QueueID] ASC +)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +) +END +GO + +SET ANSI_NULLS ON +GO +SET QUOTED_IDENTIFIER ON +GO +IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[QueueDatabase]') AND type in (N'U')) +BEGIN +CREATE TABLE [dbo].[QueueDatabase]( + [QueueID] [int] NOT NULL, + [DatabaseName] [sysname] NOT NULL, + [DatabaseOrder] [int] NULL, + [DatabaseStartTime] [datetime2](7) NULL, + [DatabaseEndTime] [datetime2](7) NULL, + [SessionID] [smallint] NULL, + [RequestID] [int] NULL, + [RequestStartTime] [datetime] NULL, + CONSTRAINT [PK_QueueDatabase] PRIMARY KEY CLUSTERED +( + [QueueID] ASC, + [DatabaseName] ASC +)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +) +END +GO +IF NOT EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_QueueDatabase_Queue]') AND parent_object_id = OBJECT_ID(N'[dbo].[QueueDatabase]')) +ALTER TABLE [dbo].[QueueDatabase] WITH CHECK ADD CONSTRAINT [FK_QueueDatabase_Queue] FOREIGN KEY([QueueID]) +REFERENCES [dbo].[Queue] ([QueueID]) +GO +IF EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_QueueDatabase_Queue]') AND parent_object_id = OBJECT_ID(N'[dbo].[QueueDatabase]')) +ALTER TABLE [dbo].[QueueDatabase] CHECK CONSTRAINT [FK_QueueDatabase_Queue] +GO + ---------------------------------------------------------------------------------------------------- GO SET ANSI_NULLS ON GO @@ -138,6 +243,9 @@ BEGIN --// License: https://ola.hallengren.com/license.html //-- --// GitHub: https://github.com/olahallengren/sql-server-maintenance-solution //-- --// Version: 2024-12-27 18:10:28 //-- + --// //-- + --// Forked Changes https://github.com/amazon-contributing/aws-sql-server-maintenance-solution //-- + --// Version: 2024-12-30 12:58 //-- ---------------------------------------------------------------------------------------------------- SET NOCOUNT ON @@ -171,6 +279,28 @@ BEGIN DECLARE @RevertCommand nvarchar(max) + ---------------------------------------------------------------------------------------------------- + --// Original Copyright 2024 Ola Hallengren. Licensed under the MIT License. //-- + --// Modifications Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. //-- + DECLARE @AmazonRDS bit = CASE WHEN DB_ID('rdsadmin') IS NOT NULL AND SUSER_SNAME(0x01) = 'rdsa' THEN 1 ELSE 0 END + DECLARE @task_id INT + + DECLARE @RDSQueue TABLE ([task_id] INT, + [task_type] nvarchar(max), + [database_name] nvarchar(max), + [% complete] nvarchar(max), + [duration (mins)] nvarchar(max), + [lifecycle] nvarchar(max), + [task_info] nvarchar(max), + [last_updated] nvarchar(max), + [created_at] nvarchar(max), + [S3_object_arn] nvarchar(max), + [overwrite_s3_backup_file] nvarchar(max), + [KMS_master_key_arn] nvarchar(max), + [filepath] nvarchar(max), + [overwrite_file] BIT) + ---------------------------------------------------------------------------------------------------- + ---------------------------------------------------------------------------------------------------- --// Check core requirements //-- ---------------------------------------------------------------------------------------------------- @@ -325,9 +455,41 @@ BEGIN IF @Mode = 1 AND @Execute = 'Y' BEGIN - EXECUTE @sp_executesql @stmt = @Command - SET @Error = @@ERROR - SET @ReturnCode = @Error + ---------------------------------------------------------------------------------------------------- + --// Original Copyright 2024 Ola Hallengren. Licensed under the MIT License. //-- + --// Modifications Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. //-- + IF @AmazonRDS = 1 + BEGIN + BEGIN TRY + EXECUTE @sp_executesql @stmt = @Command + INSERT INTO @RDSQueue exec msdb..rds_task_status @db_name=@DatabaseName; + SELECT TOP 1 @task_id=task_id from @RDSQueue ORDER BY task_id DESC + INSERT INTO dbo.RDS_BackupLog (ID, task_id, [Status]) VALUES (@ID, @task_id, 'CREATED') + END TRY + BEGIN CATCH + SET @Error = ERROR_NUMBER() + SET @ErrorMessageOriginal = ERROR_MESSAGE() + BEGIN + SET @ErrorMessage = 'RDS:Msg ' + CAST(ERROR_NUMBER() AS nvarchar) + ', ' + ISNULL(ERROR_MESSAGE(),'') + + SET @Severity = CASE WHEN ERROR_NUMBER() IN(1205,1222) THEN @LockMessageSeverity ELSE 16 END + IF @ErrorMessageOriginal NOT LIKE 'A task has already been issued for database: %' + RAISERROR('%s',@Severity,1,@ErrorMessage) WITH LOG + ELSE + BEGIN + SET @ErrorMessage = 'RDS:Msg ' + CAST(ERROR_NUMBER() AS nvarchar) + ', ' + ISNULL(ERROR_MESSAGE(),'') + RAISERROR('%s',@Severity,1,@ErrorMessage) WITH NOWAIT + END + END + END CATCH + END + ELSE + BEGIN + EXECUTE @sp_executesql @stmt = @Command + SET @Error = @@ERROR + SET @ReturnCode = @Error + END + ---------------------------------------------------------------------------------------------------- END IF @Mode = 2 AND @Execute = 'Y' @@ -391,6 +553,7 @@ BEGIN END GO + SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON @@ -467,6 +630,14 @@ ALTER PROCEDURE [dbo].[DatabaseBackup] @StringDelimiter nvarchar(max) = ',', @DatabaseOrder nvarchar(max) = NULL, @DatabasesInParallel nvarchar(max) = 'N', + + ---------------------------------------------------------------------------------------------------- + --// Original Copyright 2024 Ola Hallengren. Licensed under the MIT License. //-- + --// Modifications Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. //-- +@S3BucketArn nvarchar(255) = NULL, +@kms_master_key_arn nvarchar(max) = NULL, + ---------------------------------------------------------------------------------------------------- + @LogToTable nvarchar(max) = 'N', @Execute nvarchar(max) = 'Y' @@ -479,6 +650,8 @@ BEGIN --// License: https://ola.hallengren.com/license.html //-- --// GitHub: https://github.com/olahallengren/sql-server-maintenance-solution //-- --// Version: 2024-12-27 18:10:28 //-- + --// //-- + --// Modifications Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. //-- ---------------------------------------------------------------------------------------------------- SET NOCOUNT ON @@ -543,6 +716,7 @@ BEGIN DECLARE @CurrentDate datetime2 DECLARE @CurrentDateUTC datetime2 DECLARE @CurrentCleanupDate datetime2 + DECLARE @CurrentIsDatabaseAccessible bit DECLARE @CurrentReplicaID uniqueidentifier DECLARE @CurrentAvailabilityGroupID uniqueidentifier DECLARE @CurrentAvailabilityGroup nvarchar(max) @@ -654,6 +828,15 @@ BEGIN DECLARE @Version numeric(18,10) = CAST(LEFT(CAST(SERVERPROPERTY('ProductVersion') AS nvarchar(max)),CHARINDEX('.',CAST(SERVERPROPERTY('ProductVersion') AS nvarchar(max))) - 1) + '.' + REPLACE(RIGHT(CAST(SERVERPROPERTY('ProductVersion') AS nvarchar(max)), LEN(CAST(SERVERPROPERTY('ProductVersion') AS nvarchar(max))) - CHARINDEX('.',CAST(SERVERPROPERTY('ProductVersion') AS nvarchar(max)))),'.','') AS numeric(18,10)) + ---------------------------------------------------------------------------------------------------- + --// Original Copyright 2024 Ola Hallengren. Licensed under the MIT License. //-- + --// Modifications Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. //-- + DECLARE @CurrentRDSBackupType nvarchar(20) + DECLARE @CurrentRDSDatabaseFileName nvarchar(4000) + + DECLARE @ServerName nvarchar(max) = CASE WHEN SERVERPROPERTY('EngineEdition') = 8 THEN LEFT(CAST(SERVERPROPERTY('ServerName') AS nvarchar(max)),CHARINDEX('.',CAST(SERVERPROPERTY('ServerName') AS nvarchar(max))) - 1) ELSE CAST(SERVERPROPERTY('MachineName') AS nvarchar(max)) END + ---------------------------------------------------------------------------------------------------- + IF @Version >= 14 BEGIN SELECT @HostPlatform = host_platform @@ -737,6 +920,13 @@ BEGIN SET @Parameters += ', @LogToTable = ' + ISNULL('''' + REPLACE(@LogToTable,'''','''''') + '''','NULL') SET @Parameters += ', @Execute = ' + ISNULL('''' + REPLACE(@Execute,'''','''''') + '''','NULL') + ---------------------------------------------------------------------------------------------------- + --// Original Copyright 2024 Ola Hallengren. Licensed under the MIT License. //-- + --// Modifications Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. //-- + SET @Parameters += ', @S3BucketArn = ' + ISNULL('''' + REPLACE(@S3BucketArn,'''','''''') + '''','NULL') + SET @Parameters += ', @kms_master_key_arn = ' + ISNULL('''' + REPLACE(@kms_master_key_arn,'''','''''') + '''','NULL') + ---------------------------------------------------------------------------------------------------- + SET @StartMessage = 'Date and time: ' + CONVERT(nvarchar,@StartTime,120) RAISERROR('%s',10,1,@StartMessage) WITH NOWAIT @@ -824,11 +1014,36 @@ BEGIN SELECT 'The transaction count is not 0.', 16, 1 END - IF @AmazonRDS = 1 + --IF @AmazonRDS = 1 AND (@S3BucketArn = NULL OR @S3BucketArn = '') + --BEGIN + -- INSERT INTO @Errors ([Message], Severity, [State]) + -- SELECT 'The parameter @S3BucketArn is a required for Amazon RDS backups.', 16, 1 + --END + + ---------------------------------------------------------------------------------------------------- + --// Original Copyright 2024 Ola Hallengren. Licensed under the MIT License. //-- + --// Modifications Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. //-- + IF (@AmazonRDS = 1) BEGIN - INSERT INTO @Errors ([Message], Severity, [State]) - SELECT 'The stored procedure DatabaseBackup is not supported on Amazon RDS.', 16, 1 + IF (@AmazonRDS = 1 AND @S3BucketArn IS NULL) OR (@AmazonRDS = 1 AND @S3BucketArn = '') + BEGIN + INSERT INTO @Errors ([Message], Severity, [State]) + SELECT 'The parameter @S3BucketArn is a required for Amazon RDS backups.', 16, 1 + END + + IF (@S3BucketArn NOT LIKE 'arn:aws:s3:%' AND @S3BucketArn != '') + BEGIN + INSERT INTO @Errors ([Message], Severity, [State]) + SELECT 'The parameter @S3BucketArn is invalid.', 16, 1 + END + + IF (@kms_master_key_arn NOT LIKE 'arn:aws:kms:%' AND @kms_master_key_arn != '') + BEGIN + INSERT INTO @Errors ([Message], Severity, [State]) + SELECT 'The parameter @kms_master_key_arn is invalid.', 16, 1 + END END + ---------------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------- --// Select databases //-- @@ -1279,14 +1494,21 @@ BEGIN BREAK END - INSERT INTO @DirectoryInfo (FileExists, FileIsADirectory, ParentDirectoryExists) - EXECUTE [master].dbo.xp_fileexist @CurrentRootDirectoryPath + ---------------------------------------------------------------------------------------------------- + --// Original Copyright 2024 Ola Hallengren. Licensed under the MIT License. //-- + --// Modifications Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. //-- + IF @AmazonRDS = 0 + BEGIN + INSERT INTO @DirectoryInfo (FileExists, FileIsADirectory, ParentDirectoryExists) + EXECUTE [master].dbo.xp_fileexist @CurrentRootDirectoryPath - IF NOT EXISTS (SELECT * FROM @DirectoryInfo WHERE FileExists = 0 AND FileIsADirectory = 1 AND ParentDirectoryExists = 1) - BEGIN - INSERT INTO @Errors ([Message], Severity, [State]) - SELECT 'The directory ' + @CurrentRootDirectoryPath + ' does not exist.', 16, 1 - END + IF NOT EXISTS (SELECT * FROM @DirectoryInfo WHERE FileExists = 0 AND FileIsADirectory = 1 AND ParentDirectoryExists = 1) + BEGIN + INSERT INTO @Errors ([Message], Severity, [State]) + SELECT 'The directory ' + @CurrentRootDirectoryPath + ' does not exist.', 16, 1 + END + END + ---------------------------------------------------------------------------------------------------- UPDATE @Directories SET Completed = 1 @@ -1530,7 +1752,11 @@ BEGIN IF @CleanupTime IS NOT NULL AND @URL IS NOT NULL BEGIN INSERT INTO @Errors ([Message], Severity, [State]) - SELECT 'The value for the parameter @CleanupTime is not supported. Cleanup is not supported on Azure Blob Storage.', 16, 2 + ---------------------------------------------------------------------------------------------------- + --// Original Copyright 2024 Ola Hallengren. Licensed under the MIT License. //-- + --// Modifications Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. //-- + SELECT 'The value for the parameter @CleanupTime is not supported. Cleanup is not supported on Amazon S3 or Azure Blob Storage.', 16, 2 + ---------------------------------------------------------------------------------------------------- END IF @CleanupTime IS NOT NULL AND EXISTS(SELECT * FROM @Directories WHERE DirectoryPath = 'NUL') @@ -1825,6 +2051,16 @@ BEGIN SELECT 'The value for the parameter @NumberOfFiles is not supported. The maximum number of files when performing mirrored backups to S3 storage is 32.', 16, 10 END + ---------------------------------------------------------------------------------------------------- + --// Original Copyright 2024 Ola Hallengren. Licensed under the MIT License. //-- + --// Modifications Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. //-- + IF @NumberOfFiles > 10 AND @AmazonRDS = 1 + BEGIN + INSERT INTO @Errors ([Message], Severity, [State]) + SELECT 'The value for the parameter @NumberOfFiles is not supported. The maximum number of files when performing Amazon RDS backups is 10.', 16, 10 + END + ---------------------------------------------------------------------------------------------------- + ---------------------------------------------------------------------------------------------------- IF @MinBackupSizeForMultipleFiles <= 0 @@ -3071,6 +3307,18 @@ BEGIN WHEN @MaxTransferSize IS NULL AND @Compress = 'Y' AND @CurrentIsEncrypted = 1 AND @BackupSoftware IS NULL AND (@Version >= 13 AND @Version < 15.0404316) AND @Credential IS NULL THEN 65537 END + IF @CurrentDatabaseState = 'ONLINE' AND NOT (@CurrentInStandby = 1) + BEGIN + IF EXISTS (SELECT * FROM sys.database_recovery_status WHERE database_id = DB_ID(@CurrentDatabaseName) AND database_guid IS NOT NULL) + BEGIN + SET @CurrentIsDatabaseAccessible = 1 + END + ELSE + BEGIN + SET @CurrentIsDatabaseAccessible = 0 + END + END + IF @Version >= 11 AND SERVERPROPERTY('IsHadrEnabled') = 1 BEGIN SELECT @CurrentReplicaID = databases.replica_id @@ -3189,14 +3437,27 @@ BEGIN FROM sys.database_mirroring WHERE database_id = DB_ID(@CurrentDatabaseName) - IF EXISTS (SELECT * FROM msdb.dbo.log_shipping_primary_databases WHERE primary_database = @CurrentDatabaseName) + ---------------------------------------------------------------------------------------------------- + --// Original Copyright 2024 Ola Hallengren. Licensed under the MIT License. //-- + --// Modifications Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. //-- + IF @AmazonRDS = 0 BEGIN - SET @CurrentLogShippingRole = 'PRIMARY' - END - ELSE - IF EXISTS (SELECT * FROM msdb.dbo.log_shipping_secondary_databases WHERE secondary_database = @CurrentDatabaseName) + IF EXISTS (SELECT * FROM msdb.dbo.log_shipping_primary_databases WHERE primary_database = @CurrentDatabaseName) + BEGIN + SET @CurrentLogShippingRole = 'PRIMARY' + END + ELSE + IF EXISTS (SELECT * FROM msdb.dbo.log_shipping_secondary_databases WHERE secondary_database = @CurrentDatabaseName) + BEGIN + SET @CurrentLogShippingRole = 'SECONDARY' + END + END + ---------------------------------------------------------------------------------------------------- + + IF @CurrentIsDatabaseAccessible IS NOT NULL BEGIN - SET @CurrentLogShippingRole = 'SECONDARY' + SET @DatabaseMessage = 'Is accessible: ' + CASE WHEN @CurrentIsDatabaseAccessible = 1 THEN 'Yes' ELSE 'No' END + RAISERROR('%s',10,1,@DatabaseMessage) WITH NOWAIT END IF @CurrentAvailabilityGroup IS NOT NULL @@ -3259,7 +3520,7 @@ BEGIN RAISERROR(@EmptyLine,10,1) WITH NOWAIT IF @CurrentDatabaseState = 'ONLINE' - AND NOT (@CurrentUserAccess = 'SINGLE_USER') + AND NOT (@CurrentUserAccess = 'SINGLE_USER' AND @CurrentIsDatabaseAccessible = 0) AND NOT (@CurrentInStandby = 1) AND NOT (@CurrentBackupType = 'LOG' AND @CurrentRecoveryModel = 'SIMPLE') AND NOT (@CurrentBackupType = 'LOG' AND @CurrentRecoveryModel IN('FULL','BULK_LOGGED') AND @CurrentLogLSN IS NULL) @@ -3798,6 +4059,13 @@ BEGIN -- Create directory IF @HostPlatform = 'Windows' AND (@BackupSoftware <> 'DATA_DOMAIN_BOOST' OR @BackupSoftware IS NULL) + + ---------------------------------------------------------------------------------------------------- + --// Original Copyright 2024 Ola Hallengren. Licensed under the MIT License. //-- + --// Modifications Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. //-- + AND (@AmazonRDS = 0) + ---------------------------------------------------------------------------------------------------- + AND NOT EXISTS(SELECT * FROM @CurrentDirectories WHERE DirectoryPath = 'NUL' OR DirectoryPath IN(SELECT DirectoryPath FROM @Directories)) BEGIN WHILE (1 = 1) @@ -3951,76 +4219,110 @@ BEGIN -- Perform a backup IF NOT EXISTS (SELECT * FROM @CurrentDirectories WHERE DirectoryPath <> 'NUL' AND DirectoryPath NOT IN(SELECT DirectoryPath FROM @Directories) AND (CreateOutput <> 0 OR CreateOutput IS NULL)) - OR @HostPlatform = 'Linux' + ---------------------------------------------------------------------------------------------------- + --// Original Copyright 2024 Ola Hallengren. Licensed under the MIT License. //-- + --// Modifications Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. //-- + OR @HostPlatform = 'Linux' OR @AmazonRDS = 1 BEGIN IF @BackupSoftware IS NULL - BEGIN - SET @CurrentDatabaseContext = 'master' - - SELECT @CurrentCommandType = CASE - WHEN @CurrentBackupType IN('DIFF','FULL') THEN 'BACKUP_DATABASE' - WHEN @CurrentBackupType = 'LOG' THEN 'BACKUP_LOG' - END - - SELECT @CurrentCommand = CASE - WHEN @CurrentBackupType IN('DIFF','FULL') THEN 'BACKUP DATABASE ' + QUOTENAME(@CurrentDatabaseName) - WHEN @CurrentBackupType = 'LOG' THEN 'BACKUP LOG ' + QUOTENAME(@CurrentDatabaseName) - END - - IF @ReadWriteFileGroups = 'Y' AND @CurrentDatabaseName <> 'master' SET @CurrentCommand += ' READ_WRITE_FILEGROUPS' - - SET @CurrentCommand += ' TO' - - SELECT @CurrentCommand += ' ' + [Type] + ' = N''' + REPLACE(FilePath,'''','''''') + '''' + CASE WHEN ROW_NUMBER() OVER (ORDER BY FilePath ASC) <> @CurrentNumberOfFiles THEN ',' ELSE '' END - FROM @CurrentFiles - WHERE Mirror = 0 - ORDER BY FilePath ASC - - IF EXISTS(SELECT * FROM @CurrentFiles WHERE Mirror = 1) - BEGIN - SET @CurrentCommand += ' MIRROR TO' - - SELECT @CurrentCommand += ' ' + [Type] + ' = N''' + REPLACE(FilePath,'''','''''') + '''' + CASE WHEN ROW_NUMBER() OVER (ORDER BY FilePath ASC) <> @CurrentNumberOfFiles THEN ',' ELSE '' END - FROM @CurrentFiles - WHERE Mirror = 1 - ORDER BY FilePath ASC - END - - SET @CurrentCommand += ' WITH ' - IF @CheckSum = 'Y' SET @CurrentCommand += 'CHECKSUM' - IF @CheckSum = 'N' SET @CurrentCommand += 'NO_CHECKSUM' - IF @Version >= 10 - BEGIN - SET @CurrentCommand += CASE WHEN @Compress = 'Y' AND (@CurrentIsEncrypted = 0 OR (@CurrentIsEncrypted = 1 AND ((@Version >= 13 AND @CurrentMaxTransferSize >= 65537) OR @Version >= 15.0404316 OR SERVERPROPERTY('EngineEdition') = 8))) THEN ', COMPRESSION' ELSE ', NO_COMPRESSION' END - END + BEGIN + IF @AmazonRDS = 1 + BEGIN + SET @CurrentDatabaseContext = 'master' + + SELECT @CurrentCommandType = CASE + WHEN @CurrentBackupType IN('DIFF','FULL') THEN 'BACKUP_DATABASE' + + END + + SELECT @CurrentRDSBackupType = CASE + WHEN @CurrentBackupType = 'DIFF' THEN 'DIFFERENTIAL' + WHEN @CurrentBackupType = 'FULL' THEN 'FULL' + END + + IF @CurrentNumberOfFiles > 10 SET @CurrentNumberOfFiles = 10 + + SET @CurrentDatabaseFileName = @ServerName + '/' + @CurrentDatabaseFileName + + IF @CurrentNumberOfFiles > 1 + SELECT @CurrentDatabaseFileName=REPLACE(@CurrentDatabaseFileName,'_{FileNumber}','*'); + + IF (@kms_master_key_arn IS NULL) + SET @kms_master_key_arn = '' + + SET @CurrentCommand = 'EXEC msdb.dbo.rds_backup_database @source_db_name = ' + QUOTENAME(@CurrentDatabaseName) + ', @s3_arn_to_backup_to = ' + '''' + @S3BucketArn + '/' + @CurrentDatabaseFileName + '''' + ', @kms_master_key_arn = ' + '''' + @kms_master_key_arn + '''' + ', @overwrite_s3_backup_file=1 ' + ', @type=' + '''' + @CurrentRDSBackupType + '''' + ', @number_of_files= ' + CAST(@CurrentNumberOfFiles AS VarChar(2)) + ';' + END + ELSE + ---------------------------------------------------------------------------------------------------- + BEGIN + SET @CurrentDatabaseContext = 'master' - IF @Compress = 'Y' AND @CompressionAlgorithm IS NOT NULL - BEGIN - SET @CurrentCommand += ' (ALGORITHM = ' + @CompressionAlgorithm + ')' - END + SELECT @CurrentCommandType = CASE + WHEN @CurrentBackupType IN('DIFF','FULL') THEN 'BACKUP_DATABASE' + WHEN @CurrentBackupType = 'LOG' THEN 'BACKUP_LOG' + END - IF @CurrentBackupType = 'DIFF' SET @CurrentCommand += ', DIFFERENTIAL' + SELECT @CurrentCommand = CASE + WHEN @CurrentBackupType IN('DIFF','FULL') THEN 'BACKUP DATABASE ' + QUOTENAME(@CurrentDatabaseName) + WHEN @CurrentBackupType = 'LOG' THEN 'BACKUP LOG ' + QUOTENAME(@CurrentDatabaseName) + END + + IF @ReadWriteFileGroups = 'Y' AND @CurrentDatabaseName <> 'master' SET @CurrentCommand += ' READ_WRITE_FILEGROUPS' - IF EXISTS(SELECT * FROM @CurrentFiles WHERE Mirror = 1) - BEGIN - SET @CurrentCommand += ', FORMAT' - END + SET @CurrentCommand += ' TO' - IF @CopyOnly = 'Y' SET @CurrentCommand += ', COPY_ONLY' - IF @NoRecovery = 'Y' AND @CurrentBackupType = 'LOG' SET @CurrentCommand += ', NORECOVERY' - IF @Init = 'Y' SET @CurrentCommand += ', INIT' - IF @Format = 'Y' SET @CurrentCommand += ', FORMAT' - IF @BlockSize IS NOT NULL SET @CurrentCommand += ', BLOCKSIZE = ' + CAST(@BlockSize AS nvarchar) - IF @BufferCount IS NOT NULL SET @CurrentCommand += ', BUFFERCOUNT = ' + CAST(@BufferCount AS nvarchar) - IF @CurrentMaxTransferSize IS NOT NULL SET @CurrentCommand += ', MAXTRANSFERSIZE = ' + CAST(@CurrentMaxTransferSize AS nvarchar) - IF @Description IS NOT NULL SET @CurrentCommand += ', DESCRIPTION = N''' + REPLACE(@Description,'''','''''') + '''' - IF @BackupOptions IS NOT NULL SET @CurrentCommand += ', BACKUP_OPTIONS = N''' + REPLACE(@BackupOptions,'''','''''') + '''' - IF @Encrypt = 'Y' SET @CurrentCommand += ', ENCRYPTION (ALGORITHM = ' + UPPER(@EncryptionAlgorithm) + ', ' - IF @Encrypt = 'Y' AND @ServerCertificate IS NOT NULL SET @CurrentCommand += 'SERVER CERTIFICATE = ' + QUOTENAME(@ServerCertificate) - IF @Encrypt = 'Y' AND @ServerAsymmetricKey IS NOT NULL SET @CurrentCommand += 'SERVER ASYMMETRIC KEY = ' + QUOTENAME(@ServerAsymmetricKey) - IF @Encrypt = 'Y' SET @CurrentCommand += ')' - IF @URL IS NOT NULL AND @Credential IS NOT NULL SET @CurrentCommand += ', CREDENTIAL = N''' + REPLACE(@Credential,'''','''''') + '''' + SELECT @CurrentCommand += ' ' + [Type] + ' = N''' + REPLACE(FilePath,'''','''''') + '''' + CASE WHEN ROW_NUMBER() OVER (ORDER BY FilePath ASC) <> @CurrentNumberOfFiles THEN ',' ELSE '' END + FROM @CurrentFiles + WHERE Mirror = 0 + ORDER BY FilePath ASC + + IF EXISTS(SELECT * FROM @CurrentFiles WHERE Mirror = 1) + BEGIN + SET @CurrentCommand += ' MIRROR TO' + + SELECT @CurrentCommand += ' ' + [Type] + ' = N''' + REPLACE(FilePath,'''','''''') + '''' + CASE WHEN ROW_NUMBER() OVER (ORDER BY FilePath ASC) <> @CurrentNumberOfFiles THEN ',' ELSE '' END + FROM @CurrentFiles + WHERE Mirror = 1 + ORDER BY FilePath ASC + END + + SET @CurrentCommand += ' WITH ' + IF @CheckSum = 'Y' SET @CurrentCommand += 'CHECKSUM' + IF @CheckSum = 'N' SET @CurrentCommand += 'NO_CHECKSUM' + + IF @Version >= 10 + BEGIN + SET @CurrentCommand += CASE WHEN @Compress = 'Y' AND (@CurrentIsEncrypted = 0 OR (@CurrentIsEncrypted = 1 AND ((@Version >= 13 AND @CurrentMaxTransferSize >= 65537) OR @Version >= 15.0404316 OR SERVERPROPERTY('EngineEdition') = 8))) THEN ', COMPRESSION' ELSE ', NO_COMPRESSION' END + END + + IF @Compress = 'Y' AND @CompressionAlgorithm IS NOT NULL + BEGIN + SET @CurrentCommand += ' (ALGORITHM = ' + @CompressionAlgorithm + ')' + END + + IF @CurrentBackupType = 'DIFF' SET @CurrentCommand += ', DIFFERENTIAL' + + IF EXISTS(SELECT * FROM @CurrentFiles WHERE Mirror = 1) + BEGIN + SET @CurrentCommand += ', FORMAT' + END + + IF @CopyOnly = 'Y' SET @CurrentCommand += ', COPY_ONLY' + IF @NoRecovery = 'Y' AND @CurrentBackupType = 'LOG' SET @CurrentCommand += ', NORECOVERY' + IF @Init = 'Y' SET @CurrentCommand += ', INIT' + IF @Format = 'Y' SET @CurrentCommand += ', FORMAT' + IF @BlockSize IS NOT NULL SET @CurrentCommand += ', BLOCKSIZE = ' + CAST(@BlockSize AS nvarchar) + IF @BufferCount IS NOT NULL SET @CurrentCommand += ', BUFFERCOUNT = ' + CAST(@BufferCount AS nvarchar) + IF @CurrentMaxTransferSize IS NOT NULL SET @CurrentCommand += ', MAXTRANSFERSIZE = ' + CAST(@CurrentMaxTransferSize AS nvarchar) + IF @Description IS NOT NULL SET @CurrentCommand += ', DESCRIPTION = N''' + REPLACE(@Description,'''','''''') + '''' + IF @BackupOptions IS NOT NULL SET @CurrentCommand += ', BACKUP_OPTIONS = N''' + REPLACE(@BackupOptions,'''','''''') + '''' + IF @Encrypt = 'Y' SET @CurrentCommand += ', ENCRYPTION (ALGORITHM = ' + UPPER(@EncryptionAlgorithm) + ', ' + IF @Encrypt = 'Y' AND @ServerCertificate IS NOT NULL SET @CurrentCommand += 'SERVER CERTIFICATE = ' + QUOTENAME(@ServerCertificate) + IF @Encrypt = 'Y' AND @ServerAsymmetricKey IS NOT NULL SET @CurrentCommand += 'SERVER ASYMMETRIC KEY = ' + QUOTENAME(@ServerAsymmetricKey) + IF @Encrypt = 'Y' SET @CurrentCommand += ')' + IF @URL IS NOT NULL AND @Credential IS NOT NULL SET @CurrentCommand += ', CREDENTIAL = N''' + REPLACE(@Credential,'''','''''') + '''' + END END IF @BackupSoftware = 'LITESPEED' @@ -4224,7 +4526,11 @@ BEGIN END -- Verify the backup - IF @CurrentBackupOutput = 0 AND @Verify = 'Y' + ---------------------------------------------------------------------------------------------------- + --// Original Copyright 2024 Ola Hallengren. Licensed under the MIT License. //-- + --// Modifications Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. //-- + IF @CurrentBackupOutput = 0 AND @Verify = 'Y' AND @AmazonRDS = 0 + ---------------------------------------------------------------------------------------------------- BEGIN WHILE (1 = 1) BEGIN @@ -4505,6 +4811,7 @@ BEGIN SET @CurrentDate = NULL SET @CurrentDateUTC = NULL SET @CurrentCleanupDate = NULL + SET @CurrentIsDatabaseAccessible = NULL SET @CurrentReplicaID = NULL SET @CurrentAvailabilityGroupID = NULL SET @CurrentAvailabilityGroup = NULL @@ -4552,6 +4859,7 @@ BEGIN END GO + SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON @@ -4626,6 +4934,7 @@ BEGIN DECLARE @CurrentInStandby bit DECLARE @CurrentRecoveryModel nvarchar(max) + DECLARE @CurrentIsDatabaseAccessible bit DECLARE @CurrentReplicaID uniqueidentifier DECLARE @CurrentAvailabilityGroupID uniqueidentifier DECLARE @CurrentAvailabilityGroup nvarchar(max) @@ -5910,6 +6219,18 @@ BEGIN RAISERROR('%s',10,1,@DatabaseMessage) WITH NOWAIT END + IF @CurrentDatabaseState IN('ONLINE','EMERGENCY') AND SERVERPROPERTY('EngineEdition') <> 5 + BEGIN + IF EXISTS (SELECT * FROM sys.database_recovery_status WHERE database_id = DB_ID(@CurrentDatabaseName) AND database_guid IS NOT NULL) + BEGIN + SET @CurrentIsDatabaseAccessible = 1 + END + ELSE + BEGIN + SET @CurrentIsDatabaseAccessible = 0 + END + END + IF @Version >= 11 AND SERVERPROPERTY('IsHadrEnabled') = 1 BEGIN SELECT @CurrentReplicaID = databases.replica_id @@ -5944,6 +6265,12 @@ BEGIN WHERE database_id = DB_ID(@CurrentDatabaseName) END + IF @CurrentIsDatabaseAccessible IS NOT NULL + BEGIN + SET @DatabaseMessage = 'Is accessible: ' + CASE WHEN @CurrentIsDatabaseAccessible = 1 THEN 'Yes' ELSE 'No' END + RAISERROR('%s',10,1,@DatabaseMessage) WITH NOWAIT + END + IF @CurrentAvailabilityGroup IS NOT NULL BEGIN SET @DatabaseMessage = 'Availability group: ' + ISNULL(@CurrentAvailabilityGroup,'N/A') @@ -5977,7 +6304,7 @@ BEGIN RAISERROR(@EmptyLine,10,1) WITH NOWAIT IF @CurrentDatabaseState IN('ONLINE','EMERGENCY') - AND NOT (@CurrentUserAccess = 'SINGLE_USER') + AND NOT (@CurrentUserAccess = 'SINGLE_USER' AND @CurrentIsDatabaseAccessible = 0) AND (@CurrentAvailabilityGroupRole = 'PRIMARY' OR @CurrentAvailabilityGroupRole IS NULL OR SERVERPROPERTY('EngineEdition') = 3) AND ((@AvailabilityGroupReplicas = 'PRIMARY' AND @CurrentAvailabilityGroupRole = 'PRIMARY') OR (@AvailabilityGroupReplicas = 'SECONDARY' AND @CurrentAvailabilityGroupRole = 'SECONDARY') OR (@AvailabilityGroupReplicas = 'PREFERRED_BACKUP_REPLICA' AND @CurrentIsPreferredBackupReplica = 1) OR @AvailabilityGroupReplicas = 'ALL' OR @CurrentAvailabilityGroupRole IS NULL) AND NOT (@CurrentIsReadOnly = 1 AND @Updateability = 'READ_WRITE') @@ -6381,6 +6708,7 @@ BEGIN SET @CurrentInStandby = NULL SET @CurrentRecoveryModel = NULL + SET @CurrentIsDatabaseAccessible = NULL SET @CurrentReplicaID = NULL SET @CurrentAvailabilityGroupID = NULL SET @CurrentAvailabilityGroup = NULL @@ -6515,6 +6843,7 @@ BEGIN DECLARE @CurrentInStandby bit DECLARE @CurrentRecoveryModel nvarchar(max) + DECLARE @CurrentIsDatabaseAccessible bit DECLARE @CurrentReplicaID uniqueidentifier DECLARE @CurrentAvailabilityGroupID uniqueidentifier DECLARE @CurrentAvailabilityGroup nvarchar(max) @@ -7892,6 +8221,18 @@ BEGIN RAISERROR('%s',10,1,@DatabaseMessage) WITH NOWAIT END + IF @CurrentDatabaseState = 'ONLINE' AND SERVERPROPERTY('EngineEdition') <> 5 + BEGIN + IF EXISTS (SELECT * FROM sys.database_recovery_status WHERE database_id = DB_ID(@CurrentDatabaseName) AND database_guid IS NOT NULL) + BEGIN + SET @CurrentIsDatabaseAccessible = 1 + END + ELSE + BEGIN + SET @CurrentIsDatabaseAccessible = 0 + END + END + IF @Version >= 11 AND SERVERPROPERTY('IsHadrEnabled') = 1 BEGIN SELECT @CurrentReplicaID = databases.replica_id @@ -7919,6 +8260,12 @@ BEGIN WHERE database_id = DB_ID(@CurrentDatabaseName) END + IF @CurrentIsDatabaseAccessible IS NOT NULL + BEGIN + SET @DatabaseMessage = 'Is accessible: ' + CASE WHEN @CurrentIsDatabaseAccessible = 1 THEN 'Yes' ELSE 'No' END + RAISERROR('%s',10,1,@DatabaseMessage) WITH NOWAIT + END + IF @CurrentAvailabilityGroup IS NOT NULL BEGIN SET @DatabaseMessage = 'Availability group: ' + ISNULL(@CurrentAvailabilityGroup,'N/A') @@ -7944,8 +8291,8 @@ BEGIN END IF @CurrentDatabaseState = 'ONLINE' - AND NOT (@CurrentUserAccess = 'SINGLE_USER') - AND NOT (@CurrentAvailabilityGroup IS NOT NULL AND (@CurrentAvailabilityGroupRole <> 'PRIMARY' OR @CurrentAvailabilityGroupRole IS NULL)) + AND NOT (@CurrentUserAccess = 'SINGLE_USER' AND @CurrentIsDatabaseAccessible = 0) + AND DATABASEPROPERTYEX(@CurrentDatabaseName,'Updateability') = 'READ_WRITE' AND (@CurrentExecuteAsUserExists = 1 OR @CurrentExecuteAsUserExists IS NULL) BEGIN @@ -8803,6 +9150,7 @@ BEGIN SET @CurrentInStandby = NULL SET @CurrentRecoveryModel = NULL + SET @CurrentIsDatabaseAccessible = NULL SET @CurrentReplicaID = NULL SET @CurrentAvailabilityGroupID = NULL SET @CurrentAvailabilityGroup = NULL @@ -8893,6 +9241,13 @@ BEGIN DECLARE @Version numeric(18,10) = CAST(LEFT(CAST(SERVERPROPERTY('ProductVersion') AS nvarchar(max)),CHARINDEX('.',CAST(SERVERPROPERTY('ProductVersion') AS nvarchar(max))) - 1) + '.' + REPLACE(RIGHT(CAST(SERVERPROPERTY('ProductVersion') AS nvarchar(max)), LEN(CAST(SERVERPROPERTY('ProductVersion') AS nvarchar(max))) - CHARINDEX('.',CAST(SERVERPROPERTY('ProductVersion') AS nvarchar(max)))),'.','') AS numeric(18,10)) DECLARE @AmazonRDS bit = CASE WHEN DB_ID('rdsadmin') IS NOT NULL AND SUSER_SNAME(0x01) = 'rdsa' THEN 1 ELSE 0 END + + ---------------------------------------------------------------------------------------------------- + --// Original Copyright 2024 Ola Hallengren. Licensed under the MIT License. //-- + --// Modifications Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. //-- + DECLARE @S3BucketArn nvarchar(max) + DECLARE @kms_master_key_arn nvarchar(max) + ---------------------------------------------------------------------------------------------------- IF @Version >= 14 BEGIN @@ -8946,6 +9301,18 @@ BEGIN FROM #Config WHERE [Name] = 'LogToTable' + ---------------------------------------------------------------------------------------------------- + --// Original Copyright 2024 Ola Hallengren. Licensed under the MIT License. //-- + --// Modifications Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. //-- + SELECT @S3BucketArn = Value + FROM #Config + WHERE [Name] = 'S3BucketArn' + + SELECT @kms_master_key_arn = Value + FROM #Config + WHERE [Name] = 'kms_master_key_arn' + ---------------------------------------------------------------------------------------------------- + SELECT @DatabaseName = Value FROM #Config WHERE [Name] = 'DatabaseName' @@ -8987,21 +9354,21 @@ BEGIN INSERT INTO @Jobs ([Name], CommandTSQL, DatabaseName, OutputFileNamePart01, OutputFileNamePart02) SELECT 'DatabaseBackup - USER_DATABASES - DIFF', - 'EXECUTE [dbo].[DatabaseBackup]' + CHAR(13) + CHAR(10) + '@Databases = ''USER_DATABASES'',' + CHAR(13) + CHAR(10) + CASE WHEN @BackupURL IS NOT NULL THEN '@URL = N''' + REPLACE(@BackupURL,'''','''''') + '''' ELSE '@Directory = ' + ISNULL('N''' + REPLACE(@BackupDirectory,'''','''''') + '''','NULL') END + ',' + CHAR(13) + CHAR(10) + '@BackupType = ''DIFF'',' + CHAR(13) + CHAR(10) + '@Verify = ''Y'',' + CHAR(13) + CHAR(10) + '@CleanupTime = ' + ISNULL(CAST(@CleanupTime AS nvarchar),'NULL') + ',' + CHAR(13) + CHAR(10) + '@CheckSum = ''Y'',' + CHAR(13) + CHAR(10) + '@LogToTable = ''' + @LogToTable + '''', + 'EXECUTE [dbo].[DatabaseBackup]' + CHAR(13) + CHAR(10) + '@Databases = ''USER_DATABASES' + CASE WHEN @AmazonRDS = 1 THEN ', -rdsadmin%' ELSE '' END + ''',' + CHAR(13) + CHAR(10) + CASE WHEN @BackupURL IS NOT NULL THEN '@URL = N''' + REPLACE(@BackupURL,'''','''''') + '''' ELSE '@Directory = ' + ISNULL('N''' + REPLACE(@BackupDirectory,'''','''''') + '''','NULL') END + ',' + CHAR(13) + CHAR(10) + '@BackupType = ''DIFF'',' + CHAR(13) + CHAR(10) + '@Verify = ''Y'',' + CHAR(13) + CHAR(10) + '@CleanupTime = ' + ISNULL(CAST(@CleanupTime AS nvarchar),'NULL') + ',' + CHAR(13) + CHAR(10) + '@CheckSum = ''Y'',' + CHAR(13) + CHAR(10) + CASE WHEN @AmazonRDS = 1 THEN '@S3BucketArn = ' + ISNULL('N''' + REPLACE(@S3BucketArn,'''','''''') + '''','NULL') + ',' + CHAR(13) + CHAR(10) ELSE '' END + CASE WHEN @AmazonRDS = 1 THEN '@kms_master_key_arn = ' + ISNULL('N''' + REPLACE(@kms_master_key_arn,'''','''''') + '''','NULL') + ',' + CHAR(13) + CHAR(10) ELSE '' END + '@LogToTable = ''' + @LogToTable + '''', @DatabaseName, 'DatabaseBackup', 'DIFF' INSERT INTO @Jobs ([Name], CommandTSQL, DatabaseName, OutputFileNamePart01, OutputFileNamePart02) SELECT 'DatabaseBackup - USER_DATABASES - FULL', - 'EXECUTE [dbo].[DatabaseBackup]' + CHAR(13) + CHAR(10) + '@Databases = ''USER_DATABASES'',' + CHAR(13) + CHAR(10) + CASE WHEN @BackupURL IS NOT NULL THEN '@URL = N''' + REPLACE(@BackupURL,'''','''''') + '''' ELSE '@Directory = ' + ISNULL('N''' + REPLACE(@BackupDirectory,'''','''''') + '''','NULL') END + ',' + CHAR(13) + CHAR(10) + '@BackupType = ''FULL'',' + CHAR(13) + CHAR(10) + '@Verify = ''Y'',' + CHAR(13) + CHAR(10) + '@CleanupTime = ' + ISNULL(CAST(@CleanupTime AS nvarchar),'NULL') + ',' + CHAR(13) + CHAR(10) + '@CheckSum = ''Y'',' + CHAR(13) + CHAR(10) + '@LogToTable = ''' + @LogToTable + '''', + 'EXECUTE [dbo].[DatabaseBackup]' + CHAR(13) + CHAR(10) + '@Databases = ''USER_DATABASES' + CASE WHEN @AmazonRDS = 1 THEN ', -rdsadmin%' ELSE '' END + ''',' + CHAR(13) + CHAR(10) + CASE WHEN @BackupURL IS NOT NULL THEN '@URL = N''' + REPLACE(@BackupURL,'''','''''') + '''' ELSE '@Directory = ' + ISNULL('N''' + REPLACE(@BackupDirectory,'''','''''') + '''','NULL') END + ',' + CHAR(13) + CHAR(10) + '@BackupType = ''FULL'',' + CHAR(13) + CHAR(10) + '@Verify = ''Y'',' + CHAR(13) + CHAR(10) + '@CleanupTime = ' + ISNULL(CAST(@CleanupTime AS nvarchar),'NULL') + ',' + CHAR(13) + CHAR(10) + '@CheckSum = ''Y'',' + CHAR(13) + CHAR(10) + CASE WHEN @AmazonRDS = 1 THEN '@S3BucketArn = ' + ISNULL('N''' + REPLACE(@S3BucketArn,'''','''''') + '''','NULL') + ',' + CHAR(13) + CHAR(10) ELSE '' END + CASE WHEN @AmazonRDS = 1 THEN '@kms_master_key_arn = ' + ISNULL('N''' + REPLACE(@kms_master_key_arn,'''','''''') + '''','NULL') + ',' + CHAR(13) + CHAR(10) ELSE '' END + '@LogToTable = ''' + @LogToTable + '''', @DatabaseName, 'DatabaseBackup', 'FULL' INSERT INTO @Jobs ([Name], CommandTSQL, DatabaseName, OutputFileNamePart01, OutputFileNamePart02) SELECT 'DatabaseBackup - USER_DATABASES - LOG', - 'EXECUTE [dbo].[DatabaseBackup]' + CHAR(13) + CHAR(10) + '@Databases = ''USER_DATABASES'',' + CHAR(13) + CHAR(10) + CASE WHEN @BackupURL IS NOT NULL THEN '@URL = N''' + REPLACE(@BackupURL,'''','''''') + '''' ELSE '@Directory = ' + ISNULL('N''' + REPLACE(@BackupDirectory,'''','''''') + '''','NULL') END + ',' + CHAR(13) + CHAR(10) + '@BackupType = ''LOG'',' + CHAR(13) + CHAR(10) + '@Verify = ''Y'',' + CHAR(13) + CHAR(10) + '@CleanupTime = ' + ISNULL(CAST(@CleanupTime AS nvarchar),'NULL') + ',' + CHAR(13) + CHAR(10) + '@CheckSum = ''Y'',' + CHAR(13) + CHAR(10) + '@LogToTable = ''' + @LogToTable + '''', + 'EXECUTE [dbo].[DatabaseBackup]' + CHAR(13) + CHAR(10) + '@Databases = ''USER_DATABASES' + CASE WHEN @AmazonRDS = 1 THEN ', -rdsadmin%' ELSE '' END + ''',' + CHAR(13) + CHAR(10) + CASE WHEN @BackupURL IS NOT NULL THEN '@URL = N''' + REPLACE(@BackupURL,'''','''''') + '''' ELSE '@Directory = ' + ISNULL('N''' + REPLACE(@BackupDirectory,'''','''''') + '''','NULL') END + ',' + CHAR(13) + CHAR(10) + '@BackupType = ''LOG'',' + CHAR(13) + CHAR(10) + '@Verify = ''Y'',' + CHAR(13) + CHAR(10) + '@CleanupTime = ' + ISNULL(CAST(@CleanupTime AS nvarchar),'NULL') + ',' + CHAR(13) + CHAR(10) + '@CheckSum = ''Y'',' + CHAR(13) + CHAR(10) + '@LogToTable = ''' + @LogToTable + '''', @DatabaseName, 'DatabaseBackup', 'LOG' @@ -9018,11 +9385,15 @@ BEGIN @DatabaseName, 'DatabaseIntegrityCheck' + ---------------------------------------------------------------------------------------------------- + --// Original Copyright 2024 Ola Hallengren. Licensed under the MIT License. //-- + --// Modifications Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. //-- INSERT INTO @Jobs ([Name], CommandTSQL, DatabaseName, OutputFileNamePart01) SELECT 'IndexOptimize - USER_DATABASES', - 'EXECUTE [dbo].[IndexOptimize]' + CHAR(13) + CHAR(10) + '@Databases = ''USER_DATABASES'',' + CHAR(13) + CHAR(10) + '@LogToTable = ''' + @LogToTable + '''', + 'EXECUTE [dbo].[IndexOptimize]' + CHAR(13) + CHAR(10) + '@Databases = ''USER_DATABASES' + CASE WHEN @AmazonRDS = 1 THEN ', -rdsadmin' ELSE '' END + ''',' + CHAR(13) + CHAR(10) + '@LogToTable = ''' + @LogToTable + '''', @DatabaseName, - 'IndexOptimize' + 'IndexOptimize' + ---------------------------------------------------------------------------------------------------- INSERT INTO @Jobs ([Name], CommandTSQL, DatabaseName, OutputFileNamePart01) SELECT 'sp_delete_backuphistory', @@ -9047,11 +9418,71 @@ BEGIN 'cmd /q /c "For /F "tokens=1 delims=" %v In (''ForFiles /P "' + COALESCE(@OutputFileDirectory,@TokenLogDirectory,@LogDirectory) + '" /m *_*_*_*.txt /d -30 2^>^&1'') do if EXIST "' + COALESCE(@OutputFileDirectory,@TokenLogDirectory,@LogDirectory) + '"\%v echo del "' + COALESCE(@OutputFileDirectory,@TokenLogDirectory,@LogDirectory) + '"\%v& del "' + COALESCE(@OutputFileDirectory,@TokenLogDirectory,@LogDirectory) + '"\%v"', 'OutputFileCleanup' + ---------------------------------------------------------------------------------------------------- + --// Original Copyright 2024 Ola Hallengren. Licensed under the MIT License. //-- + --// Modifications Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. //-- + IF @AmazonRDS = 1 + BEGIN + INSERT INTO @Jobs ([Name], CommandTSQL, DatabaseName, OutputFileNamePart01) + SELECT 'DatabaseBackup - Check RDS Backup Status', + 'DECLARE @RDSQueue TABLE ([task_id] INT, + [task_type] nvarchar(max), + [database_name] nvarchar(max), + [% complete] nvarchar(max), + [duration (mins)] nvarchar(max), + [lifecycle] nvarchar(max), + [task_info] nvarchar(max), + [last_updated] nvarchar(max), + [created_at] nvarchar(max), + [S3_object_arn] nvarchar(max), + [overwrite_s3_backup_file] nvarchar(max), + [KMS_master_key_arn] nvarchar(max), + [filepath] nvarchar(max), + [overwrite_file] BIT) + + DECLARE @Message nvarchar(4000) = '''' + + INSERT INTO @RDSQueue exec msdb..rds_task_status + + IF EXISTS( SELECT rbl.ID, rbl.task_id, rbl.[Status], rq.lifecycle + FROM [RDS_BackupLog] rbl + INNER JOIN @RDSQueue rq ON rbl.task_id = rq.task_id + WHERE rq.lifecycle = ''ERROR'' AND rbl.[Status] <> rq.lifecycle ) + SET @Message = ''RDS:Msg Errors Detected in RDS Backup Queue Status'' + + select rq.task_id, rbl.ID , rq.[task_info] , rq.lifecycle INTO #tmp1 + FROM [RDS_BackupLog] rbl + INNER JOIN @RDSQueue rq ON rbl.task_id = rq.task_id + WHERE rbl.[Status] NOT IN (''SUCCESS'',''ERROR'') + + UPDATE CommandLog + SET CommandLog.ErrorNumber = 50000, CommandLog.ErrorMessage = #tmp1.[task_info] + FROM CommandLog cl + INNER JOIN #tmp1 ON cl.ID = #tmp1.ID + WHERE #tmp1.lifecycle = ''ERROR'' + + UPDATE [RDS_BackupLog] + SET [RDS_BackupLog].[Status] = rq.[lifecycle], [RDS_BackupLog].[task_info] = rq.[task_info] + FROM [RDS_BackupLog] + INNER JOIN @RDSQueue rq ON [RDS_BackupLog].task_id = rq.task_id + WHERE [RDS_BackupLog].[Status] NOT IN (''SUCCESS'',''ERROR'') + + IF @Message <> '''' + RAISERROR(''%s'',16,1,''RDS:Msg Errors Detected in RDS Backup Queue Status'') WITH LOG', + @DatabaseName, + 'CheckRDSBackupStatus' + END + ---------------------------------------------------------------------------------------------------- + IF @AmazonRDS = 1 BEGIN UPDATE @Jobs SET Selected = 1 - WHERE [Name] IN('DatabaseIntegrityCheck - USER_DATABASES','IndexOptimize - USER_DATABASES','CommandLog Cleanup') + ---------------------------------------------------------------------------------------------------- + --// Original Copyright 2024 Ola Hallengren. Licensed under the MIT License. //-- + --// Modifications Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. //-- + WHERE [Name] IN('DatabaseIntegrityCheck - USER_DATABASES','IndexOptimize - USER_DATABASES','CommandLog Cleanup','DatabaseBackup - USER_DATABASES - FULL','DatabaseBackup - USER_DATABASES - DIFF','DatabaseBackup - Check RDS Backup Status') + ---------------------------------------------------------------------------------------------------- END ELSE IF SERVERPROPERTY('EngineEdition') = 8 BEGIN @@ -9130,6 +9561,15 @@ BEGIN IF LEN(@CurrentOutputFileName) > 200 SET @CurrentOutputFileName = NULL END + ---------------------------------------------------------------------------------------------------- + --// Original Copyright 2024 Ola Hallengren. Licensed under the MIT License. //-- + --// Modifications Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. //-- + IF @AmazonRDS = 1 + BEGIN + SET @CurrentOutputFileName = NULL + END + ---------------------------------------------------------------------------------------------------- + IF @CurrentJobStepSubSystem IS NOT NULL AND @CurrentJobStepCommand IS NOT NULL AND NOT EXISTS (SELECT * FROM msdb.dbo.sysjobs WHERE [name] = @CurrentJobName) BEGIN EXECUTE msdb.dbo.sp_add_job @job_name = @CurrentJobName, @description = @JobDescription, @category_name = @JobCategory, @owner_login_name = @JobOwner @@ -9159,3 +9599,31 @@ BEGIN END GO + ---------------------------------------------------------------------------------------------------- + --// Original Copyright 2024 Ola Hallengren. Licensed under the MIT License. //-- + --// Modifications Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. //-- +USE [msdb] +GO + +DECLARE @jobId BINARY(16) +DECLARE @ReturnCode INT + +SELECT @ReturnCode = 0 + +IF EXISTS (SELECT job_id FROM msdb.dbo.sysjobs WHERE name = N'DatabaseBackup - Check RDS Backup Status') +BEGIN + SELECT @jobId=job_id FROM msdb.dbo.sysjobs WHERE name = N'DatabaseBackup - Check RDS Backup Status' + EXEC @ReturnCode = msdb.dbo.sp_add_jobschedule @job_id=@jobId, @name=N'Every 5 Minutes', + @enabled=1, + @freq_type=4, + @freq_interval=1, + @freq_subday_type=4, + @freq_subday_interval=5, + @freq_relative_interval=0, + @freq_recurrence_factor=0, + @active_start_date=20000101, + @active_end_date=99991231, + @active_start_time=0, + @active_end_time=235959 +END + ---------------------------------------------------------------------------------------------------- \ No newline at end of file diff --git a/RDS_BackupLog.sql b/RDS_BackupLog.sql new file mode 100644 index 0000000..fea470f --- /dev/null +++ b/RDS_BackupLog.sql @@ -0,0 +1,32 @@ +/* +MIT License + +Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +*/ + +SET ANSI_NULLS ON +GO +SET QUOTED_IDENTIFIER ON +GO +IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[RDS_BackupLog]') AND type in (N'U')) +BEGIN +CREATE TABLE [dbo].[RDS_BackupLog]( + [ID] [int] NOT NULL, + [task_id] [int] NOT NULL, + [Status] [nvarchar](max) NULL, + [task_Info] [nvarchar](max) NULL, + CONSTRAINT [PK_RDS_BackupLog] PRIMARY KEY CLUSTERED +( + [ID] ASC, [task_id] ASC +)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +) +GO + + diff --git a/README.md b/README.md index 9583a0e..6dea204 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,12 @@ [![bug report badge]][bug report] [![feature request badge]][feature request] +## Notes regarding this Repo + +This fork from https://github.com/olahallengren/sql-server-maintenance-solution is to address requests for support to use Amazon RDS for SQL Server. + +This repo will accept pull requests related to that specific functionality but larger functionality requests should continue to be presented to the upstream repo as the owner of the original code. Unfortunately, we are a small team and do not have the bandwidth to review and accept PRs outside of this scope. + ## Getting Started Download [MaintenanceSolution.sql](/MaintenanceSolution.sql). @@ -21,7 +27,7 @@ You can also download the objects as separate scripts: Note that you always need CommandExecute; DatabaseBackup, DatabaseIntegrityCheck, and IndexOptimize are using it. You need CommandLog if you are going to use the option to log commands to a table. -Supported versions: SQL Server 2008, SQL Server 2008 R2, SQL Server 2012, SQL Server 2014, SQL Server 2016, SQL Server 2017, SQL Server 2019, SQL Server 2022, Azure SQL Database, and Azure SQL Managed Instance +Supported versions: SQL Server 2008, SQL Server 2008 R2, SQL Server 2012, SQL Server 2014, SQL Server 2016, SQL Server 2017, SQL Server 2019, SQL Server 2022, Azure SQL Database, Azure SQL Managed Instance and [Supported Amazon RDS for SQL Server Versions](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_SQLServer.html#SQLServer.Concepts.General.VersionSupport) ## Documentation @@ -29,18 +35,20 @@ Supported versions: SQL Server 2008, SQL Server 2008 R2, SQL Server 2012, SQL Se
  • Backup: https://ola.hallengren.com/sql-server-backup.html
  • Integrity Check: https://ola.hallengren.com/sql-server-integrity-check.html
  • Index and Statistics Maintenance: https://ola.hallengren.com/sql-server-index-and-statistics-maintenance.html
  • +
  • Amazon RDS for SQL Server Backup Integration: https://github.com/fill-e/Ola-Updates/blob/main/AmazonRDSBackupHelp.md
  • [licence badge]:https://img.shields.io/badge/license-MIT-blue.svg -[stars badge]:https://img.shields.io/github/stars/olahallengren/sql-server-maintenance-solution.svg -[forks badge]:https://img.shields.io/github/forks/olahallengren/sql-server-maintenance-solution.svg -[issues badge]:https://img.shields.io/github/issues/olahallengren/sql-server-maintenance-solution.svg -[bug report badge]:https://img.shields.io/github/issues/olahallengren/sql-server-maintenance-solution/Bug%20Report.svg -[feature request badge]:https://img.shields.io/github/issues/olahallengren/sql-server-maintenance-solution/Feature%20Request.svg +[stars badge]:https://img.shields.io/github/stars/amazon-contributing/aws-sql-server-maintenance-solution.svg +[forks badge]:https://img.shields.io/github/forks/amazon-contributing/aws-sql-server-maintenance-solution.svg +[issues badge]:https://img.shields.io/github/issues/amazon-contributing/aws-sql-server-maintenance-solution.svg +[bug report badge]:https://img.shields.io/github/issues/amazon-contributing/aws-sql-server-maintenance-solution/Bug%20Report.svg +[feature request badge]:https://img.shields.io/github/issues/amazon-contributing/aws-sql-server-maintenance-solution/Feature%20Request.svg [licence]:https://github.com/olahallengren/sql-server-maintenance-solution/blob/master/LICENSE -[stars]:https://github.com/olahallengren/sql-server-maintenance-solution/stargazers -[forks]:https://github.com/olahallengren/sql-server-maintenance-solution/network -[issues]:https://github.com/olahallengren/sql-server-maintenance-solution/issues -[bug report]:https://github.com/olahallengren/sql-server-maintenance-solution/issues?q=is%3Aopen+is%3Aissue+label%3A%22Bug+Report%22 -[feature request]:https://github.com/olahallengren/sql-server-maintenance-solution/issues?q=is%3Aopen+is%3Aissue+label%3A%22Feature+Request%22 +[stars]:https://github.com/amazon-contributing/aws-sql-server-maintenance-solution/stargazers +[forks]:https://github.com/amazon-contributing/aws-sql-server-maintenance-solution/network +[issues]:https://github.com/amazon-contributing/aws-sql-server-maintenance-solution/issues +[bug report]:https://github.com/amazon-contributing/aws-sql-server-maintenance-solution/issues?q=is%3Aopen+is%3Aissue+label%3A%22Bug+Report%22 +[feature request]:https://github.com/amazon-contributing/aws-sql-server-maintenance-solution/issues?q=is%3Aopen+is%3Aissue+label%3A%22Feature+Request%22 + From a6e5337d2882cc462c9286a70a26614250840509 Mon Sep 17 00:00:00 2001 From: ekins Date: Mon, 30 Dec 2024 13:31:02 -0600 Subject: [PATCH 02/13] Initial RDS Code changes added --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6dea204..3d00ef8 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ Supported versions: SQL Server 2008, SQL Server 2008 R2, SQL Server 2012, SQL Se
  • Backup: https://ola.hallengren.com/sql-server-backup.html
  • Integrity Check: https://ola.hallengren.com/sql-server-integrity-check.html
  • Index and Statistics Maintenance: https://ola.hallengren.com/sql-server-index-and-statistics-maintenance.html
  • -
  • Amazon RDS for SQL Server Backup Integration: https://github.com/fill-e/Ola-Updates/blob/main/AmazonRDSBackupHelp.md
  • +
  • Amazon RDS for SQL Server Backup Integration: https://github.com/amazon-contributing/aws-sql-server-maintenance-solution/blob/release-2024-12-30/AmazonRDSBackupHelp.md
  • [licence badge]:https://img.shields.io/badge/license-MIT-blue.svg From 666e91c19ca08379e72dbc43586585fe8797081c Mon Sep 17 00:00:00 2001 From: ekins Date: Mon, 30 Dec 2024 13:38:08 -0600 Subject: [PATCH 03/13] Initial RDS Code changes added --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3d00ef8..0ffa195 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ Supported versions: SQL Server 2008, SQL Server 2008 R2, SQL Server 2012, SQL Se
  • Backup: https://ola.hallengren.com/sql-server-backup.html
  • Integrity Check: https://ola.hallengren.com/sql-server-integrity-check.html
  • Index and Statistics Maintenance: https://ola.hallengren.com/sql-server-index-and-statistics-maintenance.html
  • -
  • Amazon RDS for SQL Server Backup Integration: https://github.com/amazon-contributing/aws-sql-server-maintenance-solution/blob/release-2024-12-30/AmazonRDSBackupHelp.md
  • +
  • Amazon RDS for SQL Server Backup Integration: [AmazonRDSBackupHelp[(/AmazonRDSBackupHelp.md)
  • [licence badge]:https://img.shields.io/badge/license-MIT-blue.svg From ac2b4c901770cb519da6f372e909da05a08bb9bf Mon Sep 17 00:00:00 2001 From: ekins Date: Mon, 30 Dec 2024 13:39:22 -0600 Subject: [PATCH 04/13] Initial RDS Code changes added --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0ffa195..53e35ba 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ Supported versions: SQL Server 2008, SQL Server 2008 R2, SQL Server 2012, SQL Se
  • Backup: https://ola.hallengren.com/sql-server-backup.html
  • Integrity Check: https://ola.hallengren.com/sql-server-integrity-check.html
  • Index and Statistics Maintenance: https://ola.hallengren.com/sql-server-index-and-statistics-maintenance.html
  • -
  • Amazon RDS for SQL Server Backup Integration: [AmazonRDSBackupHelp[(/AmazonRDSBackupHelp.md)
  • +
  • Amazon RDS for SQL Server Backup Integration: [AmazonRDSBackupHelp](/AmazonRDSBackupHelp.md)
  • [licence badge]:https://img.shields.io/badge/license-MIT-blue.svg From 9326a3fc7f7611128d334eae2a8324b16c7762df Mon Sep 17 00:00:00 2001 From: ekins Date: Mon, 30 Dec 2024 13:40:15 -0600 Subject: [PATCH 05/13] Initial RDS Code changes added --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 53e35ba..a13e35d 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ Supported versions: SQL Server 2008, SQL Server 2008 R2, SQL Server 2012, SQL Se
  • Backup: https://ola.hallengren.com/sql-server-backup.html
  • Integrity Check: https://ola.hallengren.com/sql-server-integrity-check.html
  • Index and Statistics Maintenance: https://ola.hallengren.com/sql-server-index-and-statistics-maintenance.html
  • -
  • Amazon RDS for SQL Server Backup Integration: [AmazonRDSBackupHelp](/AmazonRDSBackupHelp.md)
  • +
  • Amazon RDS for SQL Server Backup Integration: **url to be published shortly**
  • [licence badge]:https://img.shields.io/badge/license-MIT-blue.svg From fd14572f710c9ae3fd74b8ede8ffc77762c8835a Mon Sep 17 00:00:00 2001 From: ekins Date: Mon, 30 Dec 2024 13:41:07 -0600 Subject: [PATCH 06/13] Initial RDS Code changes added --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a13e35d..df41a6f 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ Supported versions: SQL Server 2008, SQL Server 2008 R2, SQL Server 2012, SQL Se
  • Backup: https://ola.hallengren.com/sql-server-backup.html
  • Integrity Check: https://ola.hallengren.com/sql-server-integrity-check.html
  • Index and Statistics Maintenance: https://ola.hallengren.com/sql-server-index-and-statistics-maintenance.html
  • -
  • Amazon RDS for SQL Server Backup Integration: **url to be published shortly**
  • +
  • Amazon RDS for SQL Server Backup Integration: url to be published shortly
  • [licence badge]:https://img.shields.io/badge/license-MIT-blue.svg From 811829eb1fbe1bc64f7195461106540ee24724ed Mon Sep 17 00:00:00 2001 From: ekins Date: Mon, 30 Dec 2024 13:42:48 -0600 Subject: [PATCH 07/13] Initial RDS Code changes added --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index df41a6f..d5f26f0 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,8 @@ You can also download the objects as separate scripts: - [IndexOptimize](/IndexOptimize.sql): SQL Server Index and Statistics Maintenance - [CommandExecute](/CommandExecute.sql): Stored procedure to execute and log commands - [CommandLog](/CommandLog.sql): Table to log commands + + [Amazon RD](/AmazonRDSBackupHelp.md) Note that you always need CommandExecute; DatabaseBackup, DatabaseIntegrityCheck, and IndexOptimize are using it. You need CommandLog if you are going to use the option to log commands to a table. From ef78b4bc764cb1c4a68d80f4561e0dd74e313c2c Mon Sep 17 00:00:00 2001 From: ekins Date: Mon, 30 Dec 2024 13:43:56 -0600 Subject: [PATCH 08/13] Initial RDS Code changes added --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d5f26f0..a5c0e0a 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ You can also download the objects as separate scripts: - [CommandExecute](/CommandExecute.sql): Stored procedure to execute and log commands - [CommandLog](/CommandLog.sql): Table to log commands - [Amazon RD](/AmazonRDSBackupHelp.md) + [Amazon RDS for SQL Server Backup Integration](/AmazonRDSBackupHelp.md) Note that you always need CommandExecute; DatabaseBackup, DatabaseIntegrityCheck, and IndexOptimize are using it. You need CommandLog if you are going to use the option to log commands to a table. @@ -37,7 +37,7 @@ Supported versions: SQL Server 2008, SQL Server 2008 R2, SQL Server 2012, SQL Se
  • Backup: https://ola.hallengren.com/sql-server-backup.html
  • Integrity Check: https://ola.hallengren.com/sql-server-integrity-check.html
  • Index and Statistics Maintenance: https://ola.hallengren.com/sql-server-index-and-statistics-maintenance.html
  • -
  • Amazon RDS for SQL Server Backup Integration: url to be published shortly
  • +
  • [Amazon RDS for SQL Server Backup Integration](/AmazonRDSBackupHelp.md)
  • [licence badge]:https://img.shields.io/badge/license-MIT-blue.svg From 49263ad4d4509a94c425cf291eed581adb1d3592 Mon Sep 17 00:00:00 2001 From: ekins Date: Mon, 30 Dec 2024 13:45:16 -0600 Subject: [PATCH 09/13] Initial RDS Code changes added --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a5c0e0a..f4ef52e 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ Supported versions: SQL Server 2008, SQL Server 2008 R2, SQL Server 2012, SQL Se
  • Backup: https://ola.hallengren.com/sql-server-backup.html
  • Integrity Check: https://ola.hallengren.com/sql-server-integrity-check.html
  • Index and Statistics Maintenance: https://ola.hallengren.com/sql-server-index-and-statistics-maintenance.html
  • -
  • [Amazon RDS for SQL Server Backup Integration](/AmazonRDSBackupHelp.md)
  • +
  • Amazon RDS: /AmazonRDSBackupHelp.md
  • [licence badge]:https://img.shields.io/badge/license-MIT-blue.svg From 2c50001d3f2e336ac93496e039694e4ecd456f5b Mon Sep 17 00:00:00 2001 From: ekins Date: Mon, 30 Dec 2024 13:46:28 -0600 Subject: [PATCH 10/13] Initial RDS Code changes added --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index f4ef52e..001094b 100644 --- a/README.md +++ b/README.md @@ -23,8 +23,6 @@ You can also download the objects as separate scripts: - [IndexOptimize](/IndexOptimize.sql): SQL Server Index and Statistics Maintenance - [CommandExecute](/CommandExecute.sql): Stored procedure to execute and log commands - [CommandLog](/CommandLog.sql): Table to log commands - - [Amazon RDS for SQL Server Backup Integration](/AmazonRDSBackupHelp.md) Note that you always need CommandExecute; DatabaseBackup, DatabaseIntegrityCheck, and IndexOptimize are using it. You need CommandLog if you are going to use the option to log commands to a table. @@ -37,7 +35,7 @@ Supported versions: SQL Server 2008, SQL Server 2008 R2, SQL Server 2012, SQL Se
  • Backup: https://ola.hallengren.com/sql-server-backup.html
  • Integrity Check: https://ola.hallengren.com/sql-server-integrity-check.html
  • Index and Statistics Maintenance: https://ola.hallengren.com/sql-server-index-and-statistics-maintenance.html
  • -
  • Amazon RDS: /AmazonRDSBackupHelp.md
  • +
  • Amazon RDS for SQL Server Backup Integration: URL to be published shortly
  • [licence badge]:https://img.shields.io/badge/license-MIT-blue.svg From a013c939b6738e73ed8b63b343e12afaaecb0528 Mon Sep 17 00:00:00 2001 From: ekins Date: Mon, 30 Dec 2024 13:48:13 -0600 Subject: [PATCH 11/13] Initial RDS Code changes added --- AmazonRDSBackupHelp.md | 1 - 1 file changed, 1 deletion(-) delete mode 100644 AmazonRDSBackupHelp.md diff --git a/AmazonRDSBackupHelp.md b/AmazonRDSBackupHelp.md deleted file mode 100644 index 3e44861..0000000 --- a/AmazonRDSBackupHelp.md +++ /dev/null @@ -1 +0,0 @@ -** Link to Launch Blog will replace this ** \ No newline at end of file From 8876dd263983f93b3dc7a45fb7257aeff7c62ef5 Mon Sep 17 00:00:00 2001 From: ekins Date: Fri, 3 Jan 2025 15:23:22 -0600 Subject: [PATCH 12/13] Added CreateRdsbackupMonitoring.ps1 for AWS Console configuration --- CreateRdsbackupMonitoring.ps1 | 205 ++++++++++++++++++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100644 CreateRdsbackupMonitoring.ps1 diff --git a/CreateRdsbackupMonitoring.ps1 b/CreateRdsbackupMonitoring.ps1 new file mode 100644 index 0000000..8000db8 --- /dev/null +++ b/CreateRdsbackupMonitoring.ps1 @@ -0,0 +1,205 @@ +# +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: MIT-0 +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of this +# software and associated documentation files (the "Software"), to deal in the Software +# without restriction, including without limitation the rights to use, copy, modify, +# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +<# + .SYNOPSIS + CreateRdsbackupMonitoring.ps1 + + .DESCRIPTION + This script configures RDS instances to export their Error Logs into CloudWatch, then configures a Metric and Alarm to report SQL Server backup Errors + You can run for all RDS instances in all regions or filter for a subset of regions and RDS instances + .EXAMPLE + To run for All regions and All RDS instances: + .\CreateRdsbackupMonitoring.ps1 -SnsTopic 'arn:aws:sns:xxxxx:0000000000:MySNSTopic' + + To filter for a subset of regions: + .\CreateRdsbackupMonitoring.ps1 -regions 'us-east-1,us-east-2' -SnsTopic 'arn:aws:sns:xxxxx:0000000000:MySNSTopic' + + To run for a subset of RDS Instances + .\CreateRdsbackupMonitoring.ps1 -regions 'us-east-1' -SnsTopic 'arn:aws:sns:xxxxx:0000000000:MySNSTopic' -RdsInstances 'sql-1,sql-2' + + To run for a single RDS Instances + .\CreateRdsbackupMonitoring.ps1 -regions 'us-east-1' -SnsTopic 'arn:aws:sns:xxxxx:0000000000:MySNSTopic' -RdsInstances 'sql-1' + + .NOTES + Date: 01/02/2025 + + .AUTHOR + Phil Ekins - ekins@amazon.com +#> + +Param ( + [Parameter(Mandatory=$true)] [string] $SnsTopicARN, + [Parameter(Mandatory=$false)] [String] $Regions, + [Parameter(Mandatory=$false)] [string] $RdsInstances +) + +#================================================== +# Variables +#================================================== + +$Namespace = "AWS-RDS-Backup-Errors" +$AlarmDescription = "Alarm when RDS Backup Error Detected" +$LogFilterName = "AWS-RDS-Backup-Filter" +$LogFilterPattern = "Errors Detected in RDS Backup Queue Status" + +#================================================== +# Functions +#================================================== + +Function IsvalidRegion { + [CmdletBinding()] + param ( + [String]$Region + ) + + Try { + IF (([string]::IsNullOrWhiteSpace($Region))) { + $IsvalidRegion = $false + } Else { + IF ((Get-AWSRegion -SystemName $Region -IncludeChina -IncludeGovCloud).Name -ne 'Unknown') { + $AccountNumber = $Null + $AccountNumber = Get-STSCallerIdentity -Region $Region -ErrorAction Stop | Select-Object -ExpandProperty 'Account' + $IsvalidRegion = $true + } Else { + $IsvalidRegion = $false + } + } + } Catch { + $IsvalidRegion = $false + } + Return $IsvalidRegion +} + +#================================================== +# Main +#================================================== + +IF (!([string]::IsNullOrWhiteSpace($SnsTopicARN))) { + Try { + $SnsTopic = Get-SNSTopicAttribute -TopicArn $SnsTopicARN -ErrorAction Stop + } Catch { + Write-Host "Invalid SNS Topic." + Exit + } +} Else { + Write-Host "Invalid SNS Topic." + Exit +} + +Try { + IF ([string]::IsNullOrWhiteSpace($Regions)) { + [string[]]$regions = Get-AWSRegion -IncludeChina -IncludeGovCloud -ErrorAction Stop | Where-Object { $_.Region -notlike '*-iso*' } | Select-Object -ExpandProperty 'Region' + $RegionsManuallyEntered = $false + } Else { + [string[]]$regions = $Regions.split(',') + $RegionsManuallyEntered = $true + } +} Catch [System.Exception] { + Write-Host "Failed to get Regions." + Exit +} + +ForEach ($region in $regions) { + IF (IsValidRegion $region) { + write-host "Processing: $region" + Try { + IF (!([string]::IsNullOrWhiteSpace($RdsInstances))) { + [string[]]$RdsInstances = $RdsInstances.split(',') + } Else { + [string[]]$rdsInstances = Get-RDSDBInstance -Region $region -Select DBInstances.DBInstanceIdentifier -ErrorAction Stop + } + + ForEach ($rds in $rdsInstances) { + + Write-host "Processing RDS Instance:"$rds + + $MetricName = "AWS-RDS-Backup-Metric-$rds" + $AlarmName = "AWS-RDS-Backup-Alarm-$rds" + $LogName = "/aws/rds/instance/$rds/error" + + Try { + $RdsInstanceInfo = Get-RDSDBInstance -DBInstanceIdentifier $rds -region $region -ErrorAction Stop + + IF ($RdsInstanceInfo.DBInstanceStatus -eq 'available') { + Try { + $output = Edit-RDSDBInstance -DBInstanceIdentifier $rds -CloudwatchLogsExportConfiguration_EnableLogType 'error' -ApplyImmediately $true -Region $region -ErrorAction Stop + Write-Host " - Log Export (errorlog) to CloudWatch Enabled on $rds" + } Catch { + Write-Host "Errors Occured Setting Error Log Export on $rds." + Exit + } + + Try { + IF ((Get-CWLLogGroup -LogGroupNamePattern $LogName -Region $region -ErrorAction Stop) -eq $null) { + $counter = 0 + While ( ((Get-CWLLogGroup -LogGroupNamePattern $LogName -Region $region -ErrorAction Stop) -eq $null) -AND ($counter -ge 1) ) { + Write-Host "Pausing 60 seconds for log group creation : $rds" + Start-sleep 60 + $counter ++ + } + } + } Catch { + Write-Host "Errors Occured Checking Error Log Export State on $rds." + Exit + } + + IF ((Get-CWLLogGroup -LogGroupNamePattern $LogName -Region $region -ErrorAction Stop) -eq $null) { + Write-Host "Skipping $rds, Error Log group has not been published to CloudWatch yet, re-run for $rds after error log group is created." + } Else { + Try { + $metricTransformation = @{ + MetricName = $MetricName + MetricNamespace = $Namespace + MetricValue = "1" + } + Write-CWLMetricFilter -LogGroupName $LogName -FilterName $LogFilterName -FilterPattern $LogFilterPattern -MetricTransformation $metricTransformation -region $region -ErrorAction Stop + Write-Host " - Metric Filter $LogFilterName Created on $rds" + } Catch { + Write-Host "Errors Occured Creating Metric Filter on $rds." + Exit + } + + Try { + Write-CWMetricAlarm -AlarmName $AlarmName -AlarmDescription $AlarmDescription -MetricName $MetricName -Namespace $Namespace -Statistic Minimum -Period 60 -Threshold 0 -ComparisonOperator GreaterThanThreshold -EvaluationPeriod 1 -AlarmAction $SnsTopicARN -DatapointsToAlarm 1 -TreatMissingData "notBreaching" -region $region -ErrorAction Stop + Write-Host " - Metric Alarm $AlarmName Created on $rds" + } Catch { + Write-Host "Errors Occured Creating Metric Filter Alarm on $rds." + Exit + } + } + } Else { + Write-Host " - RDS instance $rds is not available for modifications." + } + } Catch { + Write-Host "RDS instance $rds not found in region $region." + } + } + } Catch [System.Exception] { + Write-host "Skipping: $region" + $error.Clear() + } + $RdsInstances = $null + } Else { + IF ($RegionsManuallyEntered) { + Write-Host "Disabled or Invalid Region Specified: $region - Skipping" + } Else { + Write-Host "$Region not Enabled - Skipping" + } + } +} \ No newline at end of file From 50fadd0273e8ed78186ec2f041f27baa906125d7 Mon Sep 17 00:00:00 2001 From: ekins Date: Fri, 7 Mar 2025 09:17:02 -0600 Subject: [PATCH 13/13] Synced with Ola updates from 2025-02-19 21:12:35 --- CommandExecute.sql | 6 +- DatabaseBackup.sql | 352 +++++++++++++------ DatabaseIntegrityCheck.sql | 55 ++- IndexOptimize.sql | 172 +++++++--- MaintenanceSolution.sql | 675 +++++++++++++++++++++++-------------- 5 files changed, 843 insertions(+), 417 deletions(-) diff --git a/CommandExecute.sql b/CommandExecute.sql index 4581426..c4d5b6d 100644 --- a/CommandExecute.sql +++ b/CommandExecute.sql @@ -36,7 +36,7 @@ BEGIN --// Source: https://ola.hallengren.com //-- --// License: https://ola.hallengren.com/license.html //-- --// GitHub: https://github.com/olahallengren/sql-server-maintenance-solution //-- - --// Version: 2024-12-27 18:10:28 //-- + --// Version: 2025-02-19 21:12:35 //-- --// //-- --// Forked Changes https://github.com/amazon-contributing/aws-sql-server-maintenance-solution //-- --// Version: 2024-12-30 12:58 //-- @@ -99,10 +99,10 @@ BEGIN --// Check core requirements //-- ---------------------------------------------------------------------------------------------------- - IF NOT (SELECT [compatibility_level] FROM sys.databases WHERE database_id = DB_ID()) >= 90 + IF NOT (SELECT [compatibility_level] FROM sys.databases WHERE [name] = DB_NAME()) >= 90 BEGIN INSERT INTO @Errors ([Message], Severity, [State]) - SELECT 'The database ' + QUOTENAME(DB_NAME(DB_ID())) + ' has to be in compatibility level 90 or higher.', 16, 1 + SELECT 'The database ' + QUOTENAME(DB_NAME()) + ' has to be in compatibility level 90 or higher.', 16, 1 END IF NOT (SELECT uses_ansi_nulls FROM sys.sql_modules WHERE [object_id] = @@PROCID) = 1 diff --git a/DatabaseBackup.sql b/DatabaseBackup.sql index 68c8ad1..c9828b7 100644 --- a/DatabaseBackup.sql +++ b/DatabaseBackup.sql @@ -20,7 +20,7 @@ ALTER PROCEDURE [dbo].[DatabaseBackup] @CopyOnly nvarchar(max) = 'N', @ChangeBackupType nvarchar(max) = 'N', @BackupSoftware nvarchar(max) = NULL, -@CheckSum nvarchar(max) = 'N', +@Checksum nvarchar(max) = 'N', @BlockSize int = NULL, @BufferCount int = NULL, @MaxTransferSize int = NULL, @@ -29,6 +29,7 @@ ALTER PROCEDURE [dbo].[DatabaseBackup] @MaxFileSize int = NULL, @CompressionLevel int = NULL, @Description nvarchar(max) = NULL, +@BackupSetName nvarchar(max) = NULL, @Threads int = NULL, @Throttle int = NULL, @Encrypt nvarchar(max) = 'N', @@ -49,6 +50,7 @@ ALTER PROCEDURE [dbo].[DatabaseBackup] @Updateability nvarchar(max) = 'ALL', @AdaptiveCompression nvarchar(max) = NULL, @ModificationLevel int = NULL, +@MinDatabaseSizeForDifferentialBackup int = NULL, @LogSizeSinceLastLogBackup int = NULL, @TimeSinceLastLogBackup int = NULL, @DataDomainBoostHost nvarchar(max) = NULL, @@ -71,6 +73,9 @@ ALTER PROCEDURE [dbo].[DatabaseBackup] @ExcludeLogShippedFromLogBackup nvarchar(max) = 'Y', @DirectoryCheck nvarchar(max) = 'Y', @BackupOptions nvarchar(max) = NULL, +@Stats int = NULL, +@ExpireDate datetime = NULL, +@RetainDays int = NULL, @StringDelimiter nvarchar(max) = ',', @DatabaseOrder nvarchar(max) = NULL, @DatabasesInParallel nvarchar(max) = 'N', @@ -93,7 +98,7 @@ BEGIN --// Source: https://ola.hallengren.com //-- --// License: https://ola.hallengren.com/license.html //-- --// GitHub: https://github.com/olahallengren/sql-server-maintenance-solution //-- - --// Version: 2024-12-27 18:10:28 //-- + --// Version: 2025-02-19 21:12:35 //-- --// //-- --// Modifications Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. //-- ---------------------------------------------------------------------------------------------------- @@ -148,6 +153,7 @@ BEGIN DECLARE @CurrentDifferentialBaseLSN numeric(25,0) DECLARE @CurrentDifferentialBaseIsSnapshot bit DECLARE @CurrentLogLSN numeric(25,0) + DECLARE @BackupInProcess bit DECLARE @CurrentLatestBackup datetime2 DECLARE @CurrentDatabaseNameFS nvarchar(max) DECLARE @CurrentDirectoryStructure nvarchar(max) @@ -155,7 +161,7 @@ BEGIN DECLARE @CurrentMaxFilePathLength nvarchar(max) DECLARE @CurrentFileName nvarchar(max) DECLARE @CurrentDirectoryID int - DECLARE @CurrentDirectoryPath nvarchar(max) + DECLARE @CurrentDirectoryPath nvarchar(4000) DECLARE @CurrentFilePath nvarchar(max) DECLARE @CurrentDate datetime2 DECLARE @CurrentDateUTC datetime2 @@ -291,7 +297,7 @@ BEGIN SET @HostPlatform = 'Windows' END - DECLARE @AmazonRDS bit = CASE WHEN DB_ID('rdsadmin') IS NOT NULL AND SUSER_SNAME(0x01) = 'rdsa' THEN 1 ELSE 0 END + DECLARE @AmazonRDS bit = CASE WHEN EXISTS (SELECT * FROM sys.databases WHERE [name] = 'rdsadmin') AND SUSER_SNAME(0x01) = 'rdsa' THEN 1 ELSE 0 END ---------------------------------------------------------------------------------------------------- --// Log initial information //-- @@ -308,7 +314,7 @@ BEGIN SET @Parameters += ', @CopyOnly = ' + ISNULL('''' + REPLACE(@CopyOnly,'''','''''') + '''','NULL') SET @Parameters += ', @ChangeBackupType = ' + ISNULL('''' + REPLACE(@ChangeBackupType,'''','''''') + '''','NULL') SET @Parameters += ', @BackupSoftware = ' + ISNULL('''' + REPLACE(@BackupSoftware,'''','''''') + '''','NULL') - SET @Parameters += ', @CheckSum = ' + ISNULL('''' + REPLACE(@CheckSum,'''','''''') + '''','NULL') + SET @Parameters += ', @Checksum = ' + ISNULL('''' + REPLACE(@Checksum,'''','''''') + '''','NULL') SET @Parameters += ', @BlockSize = ' + ISNULL(CAST(@BlockSize AS nvarchar),'NULL') SET @Parameters += ', @BufferCount = ' + ISNULL(CAST(@BufferCount AS nvarchar),'NULL') SET @Parameters += ', @MaxTransferSize = ' + ISNULL(CAST(@MaxTransferSize AS nvarchar),'NULL') @@ -317,6 +323,7 @@ BEGIN SET @Parameters += ', @MaxFileSize = ' + ISNULL(CAST(@MaxFileSize AS nvarchar),'NULL') SET @Parameters += ', @CompressionLevel = ' + ISNULL(CAST(@CompressionLevel AS nvarchar),'NULL') SET @Parameters += ', @Description = ' + ISNULL('''' + REPLACE(@Description,'''','''''') + '''','NULL') + SET @Parameters += ', @BackupSetName = ' + ISNULL('''' + REPLACE(@BackupSetName,'''','''''') + '''','NULL') SET @Parameters += ', @Threads = ' + ISNULL(CAST(@Threads AS nvarchar),'NULL') SET @Parameters += ', @Throttle = ' + ISNULL(CAST(@Throttle AS nvarchar),'NULL') SET @Parameters += ', @Encrypt = ' + ISNULL('''' + REPLACE(@Encrypt,'''','''''') + '''','NULL') @@ -337,6 +344,7 @@ BEGIN SET @Parameters += ', @Updateability = ' + ISNULL('''' + REPLACE(@Updateability,'''','''''') + '''','NULL') SET @Parameters += ', @AdaptiveCompression = ' + ISNULL('''' + REPLACE(@AdaptiveCompression,'''','''''') + '''','NULL') SET @Parameters += ', @ModificationLevel = ' + ISNULL(CAST(@ModificationLevel AS nvarchar),'NULL') + SET @Parameters += ', @MinDatabaseSizeForDifferentialBackup = ' + ISNULL('''' + REPLACE(@MinDatabaseSizeForDifferentialBackup,'''','''''') + '''','NULL') SET @Parameters += ', @LogSizeSinceLastLogBackup = ' + ISNULL(CAST(@LogSizeSinceLastLogBackup AS nvarchar),'NULL') SET @Parameters += ', @TimeSinceLastLogBackup = ' + ISNULL(CAST(@TimeSinceLastLogBackup AS nvarchar),'NULL') SET @Parameters += ', @DataDomainBoostHost = ' + ISNULL('''' + REPLACE(@DataDomainBoostHost,'''','''''') + '''','NULL') @@ -358,6 +366,10 @@ BEGIN SET @Parameters += ', @ObjectLevelRecoveryMap = ' + ISNULL('''' + REPLACE(@ObjectLevelRecoveryMap,'''','''''') + '''','NULL') SET @Parameters += ', @ExcludeLogShippedFromLogBackup = ' + ISNULL('''' + REPLACE(@ExcludeLogShippedFromLogBackup,'''','''''') + '''','NULL') SET @Parameters += ', @DirectoryCheck = ' + ISNULL('''' + REPLACE(@DirectoryCheck,'''','''''') + '''','NULL') + SET @Parameters += ', @BackupOptions = ' + ISNULL('''' + REPLACE(@BackupOptions,'''','''''') + '''','NULL') + SET @Parameters += ', @Stats = ' + ISNULL(CAST(@Stats AS nvarchar),'NULL') + SET @Parameters += ', @ExpireDate = ' + ISNULL('''' + CONVERT(nvarchar, @ExpireDate, 21) + '''','NULL') + SET @Parameters += ', @RetainDays = ' + ISNULL(CAST(@RetainDays AS nvarchar),'NULL') SET @Parameters += ', @StringDelimiter = ' + ISNULL('''' + REPLACE(@StringDelimiter,'''','''''') + '''','NULL') SET @Parameters += ', @DatabaseOrder = ' + ISNULL('''' + REPLACE(@DatabaseOrder,'''','''''') + '''','NULL') SET @Parameters += ', @DatabasesInParallel = ' + ISNULL('''' + REPLACE(@DatabasesInParallel,'''','''''') + '''','NULL') @@ -386,7 +398,7 @@ BEGIN SET @StartMessage = 'Platform: ' + @HostPlatform RAISERROR('%s',10,1,@StartMessage) WITH NOWAIT - SET @StartMessage = 'Procedure: ' + QUOTENAME(DB_NAME(DB_ID())) + '.' + QUOTENAME(@SchemaName) + '.' + QUOTENAME(@ObjectName) + SET @StartMessage = 'Procedure: ' + QUOTENAME(DB_NAME()) + '.' + QUOTENAME(@SchemaName) + '.' + QUOTENAME(@ObjectName) RAISERROR('%s',10,1,@StartMessage) WITH NOWAIT SET @StartMessage = 'Parameters: ' + @Parameters @@ -404,10 +416,10 @@ BEGIN --// Check core requirements //-- ---------------------------------------------------------------------------------------------------- - IF NOT (SELECT [compatibility_level] FROM sys.databases WHERE database_id = DB_ID()) >= 90 + IF NOT (SELECT [compatibility_level] FROM sys.databases WHERE [name] = DB_NAME()) >= 90 BEGIN INSERT INTO @Errors ([Message], Severity, [State]) - SELECT 'The database ' + QUOTENAME(DB_NAME(DB_ID())) + ' has to be in compatibility level 90 or higher.', 16, 1 + SELECT 'The database ' + QUOTENAME(DB_NAME()) + ' has to be in compatibility level 90 or higher.', 16, 1 END IF NOT (SELECT uses_ansi_nulls FROM sys.sql_modules WHERE [object_id] = @@PROCID) = 1 @@ -458,6 +470,12 @@ BEGIN SELECT 'The transaction count is not 0.', 16, 1 END + --IF @AmazonRDS = 1 AND (@S3BucketArn = NULL OR @S3BucketArn = '') + --BEGIN + -- INSERT INTO @Errors ([Message], Severity, [State]) + -- SELECT 'The parameter @S3BucketArn is a required for Amazon RDS backups.', 16, 1 + --END + ---------------------------------------------------------------------------------------------------- --// Original Copyright 2024 Ola Hallengren. Licensed under the MIT License. //-- --// Modifications Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. //-- @@ -737,8 +755,8 @@ BEGIN SET @ErrorMessage = '' SELECT @ErrorMessage = @ErrorMessage + QUOTENAME(DatabaseName) + ', ' FROM @tmpDatabases - WHERE UPPER(DatabaseNameFS) IN(SELECT UPPER(DatabaseNameFS) FROM @tmpDatabases GROUP BY UPPER(DatabaseNameFS) HAVING COUNT(*) > 1) - AND UPPER(DatabaseNameFS) IN(SELECT UPPER(DatabaseNameFS) FROM @tmpDatabases WHERE Selected = 1) + WHERE UPPER(DatabaseNameFS) IN(SELECT UPPER(DatabaseNameFS) FROM @tmpDatabases GROUP BY UPPER(DatabaseNameFS) HAVING COUNT(*) > 1 AND MAX(CAST(Selected AS int)) = 1) + AND DATALENGTH(DatabaseNameFS) > 0 ORDER BY DatabaseName ASC OPTION (RECOMPILE) @@ -945,7 +963,7 @@ BEGIN INSERT INTO @Errors ([Message], Severity, [State]) SELECT 'The directory ' + @CurrentRootDirectoryPath + ' does not exist.', 16, 1 END - END + END ---------------------------------------------------------------------------------------------------- UPDATE @Directories @@ -1209,10 +1227,10 @@ BEGIN SELECT 'The value for the parameter @CleanupTime is not supported. Cleanup is not supported if the token {DatabaseName} is not part of the directory.', 16, 5 END - IF @CleanupTime IS NOT NULL AND ((@DirectoryStructure NOT LIKE '%{BackupType}%' OR @DirectoryStructure IS NULL) OR (SERVERPROPERTY('IsHadrEnabled') = 1 AND (@AvailabilityGroupDirectoryStructure NOT LIKE '%{BackupType}%' OR @AvailabilityGroupDirectoryStructure IS NULL))) + IF @CleanupTime IS NOT NULL AND ((@DirectoryStructure NOT LIKE '%{BackupType}%' OR @DirectoryStructure IS NULL) OR (SERVERPROPERTY('IsHadrEnabled') = 1 AND (@AvailabilityGroupDirectoryStructure NOT LIKE '%{BackupType}%' OR @AvailabilityGroupDirectoryStructure IS NULL))) AND (SELECT COUNT(*) FROM (SELECT @FileExtensionFull AS FileExtension UNION SELECT @FileExtensionDiff UNION SELECT @FileExtensionLog) FileExtension) <> 3 BEGIN INSERT INTO @Errors ([Message], Severity, [State]) - SELECT 'The value for the parameter @CleanupTime is not supported. Cleanup is not supported if the token {BackupType} is not part of the directory.', 16, 6 + SELECT 'The value for the parameter @CleanupTime is not supported. Cleanup is not supported if the token {BackupType} is not part of the directory and the file extensions are not unique.', 16, 6 END IF @CleanupTime IS NOT NULL AND @CopyOnly = 'Y' AND ((@DirectoryStructure NOT LIKE '%{CopyOnly}%' OR @DirectoryStructure IS NULL) OR (SERVERPROPERTY('IsHadrEnabled') = 1 AND (@AvailabilityGroupDirectoryStructure NOT LIKE '%{CopyOnly}%' OR @AvailabilityGroupDirectoryStructure IS NULL))) @@ -1337,10 +1355,10 @@ BEGIN ---------------------------------------------------------------------------------------------------- - IF @CheckSum NOT IN ('Y','N') OR @CheckSum IS NULL + IF @Checksum NOT IN ('Y','N') OR @Checksum IS NULL BEGIN INSERT INTO @Errors ([Message], Severity, [State]) - SELECT 'The value for the parameter @CheckSum is not supported.', 16, 1 + SELECT 'The value for the parameter @Checksum is not supported.', 16, 1 END ---------------------------------------------------------------------------------------------------- @@ -1605,6 +1623,13 @@ BEGIN ---------------------------------------------------------------------------------------------------- + IF LEN(@BackupSetName) > 128 + BEGIN + INSERT INTO @Errors ([Message], Severity, [State]) + SELECT 'The value for the parameter @BackupSetName is not supported.', 16, 1 + END + + ---------------------------------------------------------------------------------------------------- IF @Threads IS NOT NULL AND (@BackupSoftware NOT IN('LITESPEED','SQLBACKUP','SQLSAFE') OR @BackupSoftware IS NULL) BEGIN INSERT INTO @Errors ([Message], Severity, [State]) @@ -1952,16 +1977,35 @@ BEGIN SELECT 'The value for the parameter @ModificationLevel is not supported.', 16, 1 END + IF @ModificationLevel <= 0 OR @ModificationLevel > 100 + BEGIN + INSERT INTO @Errors ([Message], Severity, [State]) + SELECT 'The value for the parameter @ModificationLevel is not supported.', 16, 2 + END IF @ModificationLevel IS NOT NULL AND @ChangeBackupType = 'N' BEGIN INSERT INTO @Errors ([Message], Severity, [State]) - SELECT 'The parameter @ModificationLevel can only be used together with @ChangeBackupType = ''Y''.', 16, 2 + SELECT 'The parameter @ModificationLevel can only be used together with @ChangeBackupType = ''Y''.', 16, 3 END IF @ModificationLevel IS NOT NULL AND @BackupType <> 'DIFF' BEGIN INSERT INTO @Errors ([Message], Severity, [State]) - SELECT 'The parameter @ModificationLevel can only be used for differential backups.', 16, 3 + SELECT 'The parameter @ModificationLevel can only be used for differential backups.', 16, 4 + END + + ---------------------------------------------------------------------------------------------------- + + IF @MinDatabaseSizeForDifferentialBackup <= 0 + BEGIN + INSERT INTO @Errors ([Message], Severity, [State]) + SELECT 'The value for the parameter @MinDatabaseSizeForDifferentialBackup is not supported.', 16, 1 + END + + IF @MinDatabaseSizeForDifferentialBackup IS NOT NULL AND @BackupType <> 'DIFF' + BEGIN + INSERT INTO @Errors ([Message], Severity, [State]) + SELECT 'The parameter @MinDatabaseSizeForDifferentialBackup can only be used for differential backups.', 16, 2 END ---------------------------------------------------------------------------------------------------- @@ -2166,7 +2210,7 @@ BEGIN ---------------------------------------------------------------------------------------------------- - IF EXISTS (SELECT * FROM (SELECT REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@DirectoryStructure,'{DirectorySeparator}',''),'{ServerName}',''),'{InstanceName}',''),'{ServiceName}',''),'{ClusterName}',''),'{AvailabilityGroupName}',''),'{DatabaseName}',''),'{BackupType}',''),'{Partial}',''),'{CopyOnly}',''),'{Description}',''),'{Year}',''),'{Month}',''),'{Day}',''),'{Week}',''),'{Hour}',''),'{Minute}',''),'{Second}',''),'{Millisecond}',''),'{Microsecond}',''),'{MajorVersion}',''),'{MinorVersion}','') AS DirectoryStructure) Temp WHERE DirectoryStructure LIKE '%{%' OR DirectoryStructure LIKE '%}%') + IF EXISTS (SELECT * FROM (SELECT REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@DirectoryStructure,'{DirectorySeparator}',''),'{ServerName}',''),'{InstanceName}',''),'{ServiceName}',''),'{ClusterName}',''),'{AvailabilityGroupName}',''),'{DatabaseName}',''),'{BackupType}',''),'{Partial}',''),'{CopyOnly}',''),'{Description}',''),'{BackupSetName}',''),'{Year}',''),'{Month}',''),'{Day}',''),'{Week}',''),'{Weekday}',''),'{Hour}',''),'{Minute}',''),'{Second}',''),'{Millisecond}',''),'{Microsecond}',''),'{MajorVersion}',''),'{MinorVersion}','') AS DirectoryStructure) Temp WHERE DirectoryStructure LIKE '%{%' OR DirectoryStructure LIKE '%}%') BEGIN INSERT INTO @Errors ([Message], Severity, [State]) SELECT 'The parameter @DirectoryStructure contains one or more tokens that are not supported.', 16, 1 @@ -2174,7 +2218,7 @@ BEGIN ---------------------------------------------------------------------------------------------------- - IF EXISTS (SELECT * FROM (SELECT REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@AvailabilityGroupDirectoryStructure,'{DirectorySeparator}',''),'{ServerName}',''),'{InstanceName}',''),'{ServiceName}',''),'{ClusterName}',''),'{AvailabilityGroupName}',''),'{DatabaseName}',''),'{BackupType}',''),'{Partial}',''),'{CopyOnly}',''),'{Description}',''),'{Year}',''),'{Month}',''),'{Day}',''),'{Week}',''),'{Hour}',''),'{Minute}',''),'{Second}',''),'{Millisecond}',''),'{Microsecond}',''),'{MajorVersion}',''),'{MinorVersion}','') AS AvailabilityGroupDirectoryStructure) Temp WHERE AvailabilityGroupDirectoryStructure LIKE '%{%' OR AvailabilityGroupDirectoryStructure LIKE '%}%') + IF EXISTS (SELECT * FROM (SELECT REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@AvailabilityGroupDirectoryStructure,'{DirectorySeparator}',''),'{ServerName}',''),'{InstanceName}',''),'{ServiceName}',''),'{ClusterName}',''),'{AvailabilityGroupName}',''),'{DatabaseName}',''),'{BackupType}',''),'{Partial}',''),'{CopyOnly}',''),'{Description}',''),'{BackupSetName}',''),'{Year}',''),'{Month}',''),'{Day}',''),'{Week}',''),'{Weekday}',''),'{Hour}',''),'{Minute}',''),'{Second}',''),'{Millisecond}',''),'{Microsecond}',''),'{MajorVersion}',''),'{MinorVersion}','') AS AvailabilityGroupDirectoryStructure) Temp WHERE AvailabilityGroupDirectoryStructure LIKE '%{%' OR AvailabilityGroupDirectoryStructure LIKE '%}%') BEGIN INSERT INTO @Errors ([Message], Severity, [State]) SELECT 'The parameter @AvailabilityGroupDirectoryStructure contains one or more tokens that are not supported.', 16, 1 @@ -2182,7 +2226,7 @@ BEGIN ---------------------------------------------------------------------------------------------------- - IF EXISTS (SELECT * FROM (SELECT REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@FileName,'{DirectorySeparator}',''),'{ServerName}',''),'{InstanceName}',''),'{ServiceName}',''),'{ClusterName}',''),'{AvailabilityGroupName}',''),'{DatabaseName}',''),'{BackupType}',''),'{Partial}',''),'{CopyOnly}',''),'{Description}',''),'{Year}',''),'{Month}',''),'{Day}',''),'{Week}',''),'{Hour}',''),'{Minute}',''),'{Second}',''),'{Millisecond}',''),'{Microsecond}',''),'{FileNumber}',''),'{NumberOfFiles}',''),'{FileExtension}',''),'{MajorVersion}',''),'{MinorVersion}','') AS [FileName]) Temp WHERE [FileName] LIKE '%{%' OR [FileName] LIKE '%}%') + IF EXISTS (SELECT * FROM (SELECT REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@FileName,'{DirectorySeparator}',''),'{ServerName}',''),'{InstanceName}',''),'{ServiceName}',''),'{ClusterName}',''),'{AvailabilityGroupName}',''),'{DatabaseName}',''),'{BackupType}',''),'{Partial}',''),'{CopyOnly}',''),'{Description}',''),'{BackupSetName}',''),'{Year}',''),'{Month}',''),'{Day}',''),'{Week}',''),'{Weekday}',''),'{Hour}',''),'{Minute}',''),'{Second}',''),'{Millisecond}',''),'{Microsecond}',''),'{FileNumber}',''),'{NumberOfFiles}',''),'{FileExtension}',''),'{MajorVersion}',''),'{MinorVersion}','') AS [FileName]) Temp WHERE [FileName] LIKE '%{%' OR [FileName] LIKE '%}%') BEGIN INSERT INTO @Errors ([Message], Severity, [State]) SELECT 'The parameter @FileName contains one or more tokens that are not supported.', 16, 1 @@ -2190,7 +2234,7 @@ BEGIN ---------------------------------------------------------------------------------------------------- - IF EXISTS (SELECT * FROM (SELECT REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@AvailabilityGroupFileName,'{DirectorySeparator}',''),'{ServerName}',''),'{InstanceName}',''),'{ServiceName}',''),'{ClusterName}',''),'{AvailabilityGroupName}',''),'{DatabaseName}',''),'{BackupType}',''),'{Partial}',''),'{CopyOnly}',''),'{Description}',''),'{Year}',''),'{Month}',''),'{Day}',''),'{Week}',''),'{Hour}',''),'{Minute}',''),'{Second}',''),'{Millisecond}',''),'{Microsecond}',''),'{FileNumber}',''),'{NumberOfFiles}',''),'{FileExtension}',''),'{MajorVersion}',''),'{MinorVersion}','') AS AvailabilityGroupFileName) Temp WHERE AvailabilityGroupFileName LIKE '%{%' OR AvailabilityGroupFileName LIKE '%}%') + IF EXISTS (SELECT * FROM (SELECT REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@AvailabilityGroupFileName,'{DirectorySeparator}',''),'{ServerName}',''),'{InstanceName}',''),'{ServiceName}',''),'{ClusterName}',''),'{AvailabilityGroupName}',''),'{DatabaseName}',''),'{BackupType}',''),'{Partial}',''),'{CopyOnly}',''),'{Description}',''),'{BackupSetName}',''),'{Year}',''),'{Month}',''),'{Day}',''),'{Week}',''),'{Weekday}',''),'{Hour}',''),'{Minute}',''),'{Second}',''),'{Millisecond}',''),'{Microsecond}',''),'{FileNumber}',''),'{NumberOfFiles}',''),'{FileExtension}',''),'{MajorVersion}',''),'{MinorVersion}','') AS AvailabilityGroupFileName) Temp WHERE AvailabilityGroupFileName LIKE '%{%' OR AvailabilityGroupFileName LIKE '%}%') BEGIN INSERT INTO @Errors ([Message], Severity, [State]) SELECT 'The parameter @AvailabilityGroupFileName contains one or more tokens that are not supported.', 16, 1 @@ -2312,6 +2356,43 @@ BEGIN ---------------------------------------------------------------------------------------------------- + IF @BackupOptions IS NOT NULL AND @URL IS NULL + BEGIN + INSERT INTO @Errors ([Message], Severity, [State]) + SELECT 'The value for the parameter @BackupOptions is not supported.', 16, 1 + END + + ---------------------------------------------------------------------------------------------------- + + IF @Stats <= 0 OR @Stats > 100 + BEGIN + INSERT INTO @Errors ([Message], Severity, [State]) + SELECT 'The value for the parameter @Stats is not supported.', 16, 1 + END + + ---------------------------------------------------------------------------------------------------- + + IF @ExpireDate IS NOT NULL AND @BackupSoftware <> 'LITESPEED' + BEGIN + INSERT INTO @Errors ([Message], Severity, [State]) + SELECT 'The value for the parameter @ExpireDate is not supported.', 16, 1 + END + + ---------------------------------------------------------------------------------------------------- + + IF @RetainDays < 0 + BEGIN + INSERT INTO @Errors ([Message], Severity, [State]) + SELECT 'The value for the parameter @RetainDays is not supported.', 16, 1 + END + + IF @RetainDays IS NOT NULL AND @BackupSoftware <> 'LITESPEED' + BEGIN + INSERT INTO @Errors ([Message], Severity, [State]) + SELECT 'The value for the parameter @RetainDays is not supported.', 16, 1 + END + + ---------------------------------------------------------------------------------------------------- IF @StringDelimiter IS NULL OR LEN(@StringDelimiter) > 1 BEGIN INSERT INTO @Errors ([Message], Severity, [State]) @@ -2788,22 +2869,23 @@ BEGIN AND EXISTS(SELECT * FROM sys.all_columns WHERE object_id = OBJECT_ID('sys.dm_db_file_space_usage') AND name = 'modified_extent_page_count') AND (@CurrentAvailabilityGroupRole = 'PRIMARY' OR @CurrentAvailabilityGroupRole IS NULL) AND (@BackupType IN('DIFF','FULL') OR (@ChangeBackupType = 'Y' AND @CurrentBackupType = 'LOG' AND @CurrentRecoveryModel IN('FULL','BULK_LOGGED') AND @CurrentLogLSN IS NULL AND @CurrentDatabaseName <> 'master')) - AND (@ModificationLevel IS NOT NULL OR @MinBackupSizeForMultipleFiles IS NOT NULL OR @MaxFileSize IS NOT NULL) + AND (@ModificationLevel IS NOT NULL OR @MinBackupSizeForMultipleFiles IS NOT NULL OR @MaxFileSize IS NOT NULL OR @MinDatabaseSizeForDifferentialBackup IS NOT NULL) BEGIN SET @CurrentCommand = 'SELECT @ParamAllocatedExtentPageCount = SUM(allocated_extent_page_count), @ParamModifiedExtentPageCount = SUM(modified_extent_page_count) FROM sys.dm_db_file_space_usage' EXECUTE @CurrentDatabase_sp_executesql @stmt = @CurrentCommand, @params = N'@ParamAllocatedExtentPageCount bigint OUTPUT, @ParamModifiedExtentPageCount bigint OUTPUT', @ParamAllocatedExtentPageCount = @CurrentAllocatedExtentPageCount OUTPUT, @ParamModifiedExtentPageCount = @CurrentModifiedExtentPageCount OUTPUT END + SET @BackupInProcess = CASE WHEN EXISTS(SELECT * FROM sys.dm_exec_requests WHERE database_id = DB_ID(@CurrentDatabaseName) AND command = 'BACKUP DATABASE') THEN 1 ELSE 0 END SET @CurrentBackupType = @BackupType IF @ChangeBackupType = 'Y' BEGIN - IF @CurrentBackupType = 'LOG' AND @CurrentRecoveryModel IN('FULL','BULK_LOGGED') AND @CurrentLogLSN IS NULL AND @CurrentDatabaseName <> 'master' + IF @CurrentBackupType = 'LOG' AND @CurrentRecoveryModel IN('FULL','BULK_LOGGED') AND @CurrentLogLSN IS NULL AND @CurrentDatabaseName <> 'master' AND @BackupInProcess = 0 BEGIN SET @CurrentBackupType = 'DIFF' END - IF @CurrentBackupType = 'DIFF' AND (@CurrentDatabaseName = 'master' OR @CurrentDifferentialBaseLSN IS NULL OR (@CurrentModifiedExtentPageCount * 1. / @CurrentAllocatedExtentPageCount * 100 >= @ModificationLevel)) + IF @CurrentBackupType = 'DIFF' AND (@CurrentDatabaseName = 'master' OR @CurrentDifferentialBaseLSN IS NULL OR (@CurrentModifiedExtentPageCount * 1. / @CurrentAllocatedExtentPageCount * 100 >= @ModificationLevel) OR (COALESCE(CAST(@CurrentAllocatedExtentPageCount AS bigint) * 8192, CAST(@CurrentDatabaseSize AS bigint) * 8192) < CAST(@MinDatabaseSizeForDifferentialBackup AS bigint) * 1024 * 1024)) BEGIN SET @CurrentBackupType = 'FULL' END @@ -2860,8 +2942,9 @@ BEGIN FROM CurrentDatabase SELECT @CurrentDatabaseMirroringRole = UPPER(mirroring_role_desc) - FROM sys.database_mirroring - WHERE database_id = DB_ID(@CurrentDatabaseName) + FROM sys.database_mirroring database_mirroring + INNER JOIN sys.databases databases ON database_mirroring.database_id = databases.database_id + WHERE databases.[name] = @CurrentDatabaseName ---------------------------------------------------------------------------------------------------- --// Original Copyright 2024 Ola Hallengren. Licensed under the MIT License. //-- @@ -2880,6 +2963,12 @@ BEGIN END ---------------------------------------------------------------------------------------------------- + + + + + + IF @CurrentAvailabilityGroup IS NOT NULL BEGIN SET @DatabaseMessage = 'Availability group: ' + ISNULL(@CurrentAvailabilityGroup,'N/A') @@ -2919,6 +3008,11 @@ BEGIN SET @DatabaseMessage = 'Last log backup LSN: ' + ISNULL(CAST(@CurrentLogLSN AS nvarchar),'N/A') RAISERROR('%s',10,1,@DatabaseMessage) WITH NOWAIT + IF @CurrentBackupType = 'LOG' AND @BackupInProcess = 1 + BEGIN + SET @DatabaseMessage = 'Full or differential backup in process: ' + CASE WHEN @BackupInProcess = 1 THEN 'Yes' WHEN @BackupInProcess = 0 THEN 'No' ELSE 'N/A' END + RAISERROR('%s',10,1,@DatabaseMessage) WITH NOWAIT + END IF @CurrentBackupType IN('DIFF','FULL') AND EXISTS(SELECT * FROM sys.all_columns WHERE object_id = OBJECT_ID('sys.dm_db_file_space_usage') AND name = 'modified_extent_page_count') BEGIN SET @DatabaseMessage = 'Allocated extent page count: ' + ISNULL(CAST(@CurrentAllocatedExtentPageCount AS nvarchar) + ' (' + CAST(@CurrentAllocatedExtentPageCount * 1. * 8 / 1024 AS nvarchar) + ' MB)','N/A') @@ -2956,6 +3050,7 @@ BEGIN AND NOT (@CurrentIsReadOnly = 0 AND @Updateability = 'READ_ONLY') AND NOT (@CurrentBackupType = 'LOG' AND @LogSizeSinceLastLogBackup IS NOT NULL AND @TimeSinceLastLogBackup IS NOT NULL AND NOT(@CurrentLogSizeSinceLastLogBackup >= @LogSizeSinceLastLogBackup OR @CurrentLogSizeSinceLastLogBackup IS NULL OR DATEDIFF(SECOND,@CurrentLastLogBackup,SYSDATETIME()) >= @TimeSinceLastLogBackup OR @CurrentLastLogBackup IS NULL)) AND NOT (@CurrentBackupType = 'LOG' AND @Updateability = 'READ_ONLY' AND @BackupSoftware = 'DATA_DOMAIN_BOOST') + AND NOT (@CurrentBackupType = 'DIFF' AND @MinDatabaseSizeForDifferentialBackup IS NOT NULL AND (COALESCE(CAST(@CurrentAllocatedExtentPageCount AS bigint) * 8192, CAST(@CurrentDatabaseSize AS bigint) * 8192) < CAST(@MinDatabaseSizeForDifferentialBackup AS bigint) * 1024 * 1024)) BEGIN IF @CurrentBackupType = 'LOG' AND (@CleanupTime IS NOT NULL OR @MirrorCleanupTime IS NOT NULL) @@ -2995,6 +3090,7 @@ BEGIN IF SERVERPROPERTY('InstanceName') IS NULL SET @CurrentDirectoryStructure = REPLACE(@CurrentDirectoryStructure,'{InstanceName}','') IF @@SERVICENAME IS NULL SET @CurrentDirectoryStructure = REPLACE(@CurrentDirectoryStructure,'{ServiceName}','') IF @Description IS NULL SET @CurrentDirectoryStructure = REPLACE(@CurrentDirectoryStructure,'{Description}','') + IF @BackupSetName IS NULL SET @CurrentDirectoryStructure = REPLACE(@CurrentDirectoryStructure,'{BackupSetName}','') IF @Directory IS NULL AND @MirrorDirectory IS NULL AND @URL IS NULL AND @DefaultDirectory LIKE '%' + '.' + @@SERVICENAME + @DirectorySeparator + 'MSSQL' + @DirectorySeparator + 'Backup' BEGIN @@ -3152,10 +3248,12 @@ BEGIN SET @CurrentDirectoryStructure = REPLACE(@CurrentDirectoryStructure,'{Partial}','PARTIAL') SET @CurrentDirectoryStructure = REPLACE(@CurrentDirectoryStructure,'{CopyOnly}','COPY_ONLY') SET @CurrentDirectoryStructure = REPLACE(@CurrentDirectoryStructure,'{Description}',LTRIM(RTRIM(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(ISNULL(@Description,''),'\',''),'/',''),':',''),'*',''),'?',''),'"',''),'<',''),'>',''),'|','')))) + SET @CurrentDirectoryStructure = REPLACE(@CurrentDirectoryStructure,'{BackupSetName}',LTRIM(RTRIM(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(ISNULL(@BackupSetName,''),'\',''),'/',''),':',''),'*',''),'?',''),'"',''),'<',''),'>',''),'|','')))) SET @CurrentDirectoryStructure = REPLACE(@CurrentDirectoryStructure,'{Year}',CAST(DATEPART(YEAR,CASE WHEN @TokenTimezone = 'UTC' THEN @CurrentDateUTC ELSE @CurrentDate END) AS nvarchar)) SET @CurrentDirectoryStructure = REPLACE(@CurrentDirectoryStructure,'{Month}',RIGHT('0' + CAST(DATEPART(MONTH,CASE WHEN @TokenTimezone = 'UTC' THEN @CurrentDateUTC ELSE @CurrentDate END) AS nvarchar),2)) SET @CurrentDirectoryStructure = REPLACE(@CurrentDirectoryStructure,'{Day}',RIGHT('0' + CAST(DATEPART(DAY,CASE WHEN @TokenTimezone = 'UTC' THEN @CurrentDateUTC ELSE @CurrentDate END) AS nvarchar),2)) SET @CurrentDirectoryStructure = REPLACE(@CurrentDirectoryStructure,'{Week}',RIGHT('0' + CAST(DATEPART(WEEK,CASE WHEN @TokenTimezone = 'UTC' THEN @CurrentDateUTC ELSE @CurrentDate END) AS nvarchar),2)) + SET @CurrentDirectoryStructure = REPLACE(@CurrentDirectoryStructure,'{Weekday}',DATENAME(WEEKDAY,CASE WHEN @TokenTimezone = 'UTC' THEN @CurrentDateUTC ELSE @CurrentDate END)) SET @CurrentDirectoryStructure = REPLACE(@CurrentDirectoryStructure,'{Hour}',RIGHT('0' + CAST(DATEPART(HOUR,CASE WHEN @TokenTimezone = 'UTC' THEN @CurrentDateUTC ELSE @CurrentDate END) AS nvarchar),2)) SET @CurrentDirectoryStructure = REPLACE(@CurrentDirectoryStructure,'{Minute}',RIGHT('0' + CAST(DATEPART(MINUTE,CASE WHEN @TokenTimezone = 'UTC' THEN @CurrentDateUTC ELSE @CurrentDate END) AS nvarchar),2)) SET @CurrentDirectoryStructure = REPLACE(@CurrentDirectoryStructure,'{Second}',RIGHT('0' + CAST(DATEPART(SECOND,CASE WHEN @TokenTimezone = 'UTC' THEN @CurrentDateUTC ELSE @CurrentDate END) AS nvarchar),2)) @@ -3202,6 +3300,7 @@ BEGIN IF SERVERPROPERTY('InstanceName') IS NULL SET @CurrentDatabaseFileName = REPLACE(@CurrentDatabaseFileName,'{InstanceName}','') IF @@SERVICENAME IS NULL SET @CurrentDatabaseFileName = REPLACE(@CurrentDatabaseFileName,'{ServiceName}','') IF @Description IS NULL SET @CurrentDatabaseFileName = REPLACE(@CurrentDatabaseFileName,'{Description}','') + IF @BackupSetName IS NULL SET @CurrentDatabaseFileName = REPLACE(@CurrentDatabaseFileName,'{BackupSetName}','') IF @CurrentNumberOfFiles = 1 SET @CurrentDatabaseFileName = REPLACE(@CurrentDatabaseFileName,'{FileNumber}','') IF @CurrentNumberOfFiles = 1 SET @CurrentDatabaseFileName = REPLACE(@CurrentDatabaseFileName,'{NumberOfFiles}','') @@ -3313,10 +3412,12 @@ BEGIN SET @CurrentDatabaseFileName = REPLACE(@CurrentDatabaseFileName,'{Partial}','PARTIAL') SET @CurrentDatabaseFileName = REPLACE(@CurrentDatabaseFileName,'{CopyOnly}','COPY_ONLY') SET @CurrentDatabaseFileName = REPLACE(@CurrentDatabaseFileName,'{Description}',LTRIM(RTRIM(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(ISNULL(@Description,''),'\',''),'/',''),':',''),'*',''),'?',''),'"',''),'<',''),'>',''),'|','')))) + SET @CurrentDatabaseFileName = REPLACE(@CurrentDatabaseFileName,'{BackupSetName}',LTRIM(RTRIM(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(ISNULL(@BackupSetName,''),'\',''),'/',''),':',''),'*',''),'?',''),'"',''),'<',''),'>',''),'|','')))) SET @CurrentDatabaseFileName = REPLACE(@CurrentDatabaseFileName,'{Year}',CAST(DATEPART(YEAR,CASE WHEN @TokenTimezone = 'UTC' THEN @CurrentDateUTC ELSE @CurrentDate END) AS nvarchar)) SET @CurrentDatabaseFileName = REPLACE(@CurrentDatabaseFileName,'{Month}',RIGHT('0' + CAST(DATEPART(MONTH,CASE WHEN @TokenTimezone = 'UTC' THEN @CurrentDateUTC ELSE @CurrentDate END) AS nvarchar),2)) SET @CurrentDatabaseFileName = REPLACE(@CurrentDatabaseFileName,'{Day}',RIGHT('0' + CAST(DATEPART(DAY,CASE WHEN @TokenTimezone = 'UTC' THEN @CurrentDateUTC ELSE @CurrentDate END) AS nvarchar),2)) SET @CurrentDatabaseFileName = REPLACE(@CurrentDatabaseFileName,'{Week}',RIGHT('0' + CAST(DATEPART(WEEK,CASE WHEN @TokenTimezone = 'UTC' THEN @CurrentDateUTC ELSE @CurrentDate END) AS nvarchar),2)) + SET @CurrentDatabaseFileName = REPLACE(@CurrentDatabaseFileName,'{Weekday}',DATENAME(WEEKDAY,CASE WHEN @TokenTimezone = 'UTC' THEN @CurrentDateUTC ELSE @CurrentDate END)) SET @CurrentDatabaseFileName = REPLACE(@CurrentDatabaseFileName,'{Hour}',RIGHT('0' + CAST(DATEPART(HOUR,CASE WHEN @TokenTimezone = 'UTC' THEN @CurrentDateUTC ELSE @CurrentDate END) AS nvarchar),2)) SET @CurrentDatabaseFileName = REPLACE(@CurrentDatabaseFileName,'{Minute}',RIGHT('0' + CAST(DATEPART(MINUTE,CASE WHEN @TokenTimezone = 'UTC' THEN @CurrentDateUTC ELSE @CurrentDate END) AS nvarchar),2)) SET @CurrentDatabaseFileName = REPLACE(@CurrentDatabaseFileName,'{Second}',RIGHT('0' + CAST(DATEPART(SECOND,CASE WHEN @TokenTimezone = 'UTC' THEN @CurrentDateUTC ELSE @CurrentDate END) AS nvarchar),2)) @@ -3501,21 +3602,40 @@ BEGIN BREAK END - SET @CurrentDatabaseContext = 'master' + IF @DirectoryCheck = 'Y' + BEGIN + INSERT INTO @DirectoryInfo (FileExists, FileIsADirectory, ParentDirectoryExists) + EXECUTE [master].dbo.xp_fileexist @CurrentDirectoryPath + END + + IF NOT EXISTS (SELECT * FROM @DirectoryInfo WHERE FileExists = 0 AND FileIsADirectory = 1 AND ParentDirectoryExists = 1) + BEGIN + SET @CurrentDatabaseContext = 'master' - SET @CurrentCommandType = 'xp_create_subdir' + SET @CurrentCommandType = 'xp_create_subdir' - SET @CurrentCommand = 'DECLARE @ReturnCode int EXECUTE @ReturnCode = dbo.xp_create_subdir N''' + REPLACE(@CurrentDirectoryPath,'''','''''') + ''' IF @ReturnCode <> 0 RAISERROR(''Error creating directory.'', 16, 1)' + SET @CurrentCommand = 'DECLARE @ReturnCode int EXECUTE @ReturnCode = dbo.xp_create_subdir N''' + REPLACE(@CurrentDirectoryPath,'''','''''') + ''' IF @ReturnCode <> 0 RAISERROR(''Error creating directory.'', 16, 1)' + + + - EXECUTE @CurrentCommandOutput = dbo.CommandExecute @DatabaseContext = @CurrentDatabaseContext, @Command = @CurrentCommand, @CommandType = @CurrentCommandType, @Mode = 1, @DatabaseName = @CurrentDatabaseName, @LogToTable = @LogToTable, @Execute = @Execute - SET @Error = @@ERROR - IF @Error <> 0 SET @CurrentCommandOutput = @Error - IF @CurrentCommandOutput <> 0 SET @ReturnCode = @CurrentCommandOutput + EXECUTE @CurrentCommandOutput = dbo.CommandExecute @DatabaseContext = @CurrentDatabaseContext, @Command = @CurrentCommand, @CommandType = @CurrentCommandType, @Mode = 1, @DatabaseName = @CurrentDatabaseName, @LogToTable = @LogToTable, @Execute = @Execute + SET @Error = @@ERROR + IF @Error <> 0 SET @CurrentCommandOutput = @Error + IF @CurrentCommandOutput <> 0 SET @ReturnCode = @CurrentCommandOutput - UPDATE @CurrentDirectories - SET CreateCompleted = 1, - CreateOutput = @CurrentCommandOutput - WHERE ID = @CurrentDirectoryID + UPDATE @CurrentDirectories + SET CreateCompleted = 1, + CreateOutput = @CurrentCommandOutput + WHERE ID = @CurrentDirectoryID + END + ELSE + BEGIN + UPDATE @CurrentDirectories + SET CreateCompleted = 1, + CreateOutput = 0 + WHERE ID = @CurrentDirectoryID + END SET @CurrentDirectoryID = NULL SET @CurrentDirectoryPath = NULL @@ -3524,6 +3644,8 @@ BEGIN SET @CurrentCommand = NULL SET @CurrentCommandOutput = NULL SET @CurrentCommandType = NULL + + DELETE FROM @DirectoryInfo END END @@ -3686,64 +3808,70 @@ BEGIN SELECT @CurrentCommand = CASE WHEN @CurrentBackupType IN('DIFF','FULL') THEN 'BACKUP DATABASE ' + QUOTENAME(@CurrentDatabaseName) WHEN @CurrentBackupType = 'LOG' THEN 'BACKUP LOG ' + QUOTENAME(@CurrentDatabaseName) - END - - IF @ReadWriteFileGroups = 'Y' AND @CurrentDatabaseName <> 'master' SET @CurrentCommand += ' READ_WRITE_FILEGROUPS' + END + + - SET @CurrentCommand += ' TO' + IF @ReadWriteFileGroups = 'Y' AND @CurrentDatabaseName <> 'master' SET @CurrentCommand += ' READ_WRITE_FILEGROUPS' - SELECT @CurrentCommand += ' ' + [Type] + ' = N''' + REPLACE(FilePath,'''','''''') + '''' + CASE WHEN ROW_NUMBER() OVER (ORDER BY FilePath ASC) <> @CurrentNumberOfFiles THEN ',' ELSE '' END - FROM @CurrentFiles - WHERE Mirror = 0 - ORDER BY FilePath ASC - - IF EXISTS(SELECT * FROM @CurrentFiles WHERE Mirror = 1) - BEGIN - SET @CurrentCommand += ' MIRROR TO' - - SELECT @CurrentCommand += ' ' + [Type] + ' = N''' + REPLACE(FilePath,'''','''''') + '''' + CASE WHEN ROW_NUMBER() OVER (ORDER BY FilePath ASC) <> @CurrentNumberOfFiles THEN ',' ELSE '' END - FROM @CurrentFiles - WHERE Mirror = 1 - ORDER BY FilePath ASC - END - - SET @CurrentCommand += ' WITH ' - IF @CheckSum = 'Y' SET @CurrentCommand += 'CHECKSUM' - IF @CheckSum = 'N' SET @CurrentCommand += 'NO_CHECKSUM' - - IF @Version >= 10 - BEGIN - SET @CurrentCommand += CASE WHEN @Compress = 'Y' AND (@CurrentIsEncrypted = 0 OR (@CurrentIsEncrypted = 1 AND ((@Version >= 13 AND @CurrentMaxTransferSize >= 65537) OR @Version >= 15.0404316 OR SERVERPROPERTY('EngineEdition') = 8))) THEN ', COMPRESSION' ELSE ', NO_COMPRESSION' END - END - - IF @Compress = 'Y' AND @CompressionAlgorithm IS NOT NULL - BEGIN - SET @CurrentCommand += ' (ALGORITHM = ' + @CompressionAlgorithm + ')' - END - - IF @CurrentBackupType = 'DIFF' SET @CurrentCommand += ', DIFFERENTIAL' - - IF EXISTS(SELECT * FROM @CurrentFiles WHERE Mirror = 1) - BEGIN - SET @CurrentCommand += ', FORMAT' - END - - IF @CopyOnly = 'Y' SET @CurrentCommand += ', COPY_ONLY' - IF @NoRecovery = 'Y' AND @CurrentBackupType = 'LOG' SET @CurrentCommand += ', NORECOVERY' - IF @Init = 'Y' SET @CurrentCommand += ', INIT' - IF @Format = 'Y' SET @CurrentCommand += ', FORMAT' - IF @BlockSize IS NOT NULL SET @CurrentCommand += ', BLOCKSIZE = ' + CAST(@BlockSize AS nvarchar) - IF @BufferCount IS NOT NULL SET @CurrentCommand += ', BUFFERCOUNT = ' + CAST(@BufferCount AS nvarchar) - IF @CurrentMaxTransferSize IS NOT NULL SET @CurrentCommand += ', MAXTRANSFERSIZE = ' + CAST(@CurrentMaxTransferSize AS nvarchar) - IF @Description IS NOT NULL SET @CurrentCommand += ', DESCRIPTION = N''' + REPLACE(@Description,'''','''''') + '''' - IF @BackupOptions IS NOT NULL SET @CurrentCommand += ', BACKUP_OPTIONS = N''' + REPLACE(@BackupOptions,'''','''''') + '''' - IF @Encrypt = 'Y' SET @CurrentCommand += ', ENCRYPTION (ALGORITHM = ' + UPPER(@EncryptionAlgorithm) + ', ' - IF @Encrypt = 'Y' AND @ServerCertificate IS NOT NULL SET @CurrentCommand += 'SERVER CERTIFICATE = ' + QUOTENAME(@ServerCertificate) - IF @Encrypt = 'Y' AND @ServerAsymmetricKey IS NOT NULL SET @CurrentCommand += 'SERVER ASYMMETRIC KEY = ' + QUOTENAME(@ServerAsymmetricKey) - IF @Encrypt = 'Y' SET @CurrentCommand += ')' - IF @URL IS NOT NULL AND @Credential IS NOT NULL SET @CurrentCommand += ', CREDENTIAL = N''' + REPLACE(@Credential,'''','''''') + '''' - END - END + SET @CurrentCommand += ' TO' + + SELECT @CurrentCommand += ' ' + [Type] + ' = N''' + REPLACE(FilePath,'''','''''') + '''' + CASE WHEN ROW_NUMBER() OVER (ORDER BY FilePath ASC) <> @CurrentNumberOfFiles THEN ',' ELSE '' END + FROM @CurrentFiles + WHERE Mirror = 0 + ORDER BY FilePath ASC + + IF EXISTS(SELECT * FROM @CurrentFiles WHERE Mirror = 1) + BEGIN + SET @CurrentCommand += ' MIRROR TO' + + SELECT @CurrentCommand += ' ' + [Type] + ' = N''' + REPLACE(FilePath,'''','''''') + '''' + CASE WHEN ROW_NUMBER() OVER (ORDER BY FilePath ASC) <> @CurrentNumberOfFiles THEN ',' ELSE '' END + FROM @CurrentFiles + WHERE Mirror = 1 + ORDER BY FilePath ASC + END + + SET @CurrentCommand += ' WITH ' + IF @Checksum = 'Y' SET @CurrentCommand += 'CHECKSUM' + IF @Checksum = 'N' SET @CurrentCommand += 'NO_CHECKSUM' + + IF @Version >= 10 + BEGIN + SET @CurrentCommand += CASE WHEN @Compress = 'Y' AND (@CurrentIsEncrypted = 0 OR (@CurrentIsEncrypted = 1 AND ((@Version >= 13 AND @CurrentMaxTransferSize >= 65537) OR @Version >= 15.0404316 OR SERVERPROPERTY('EngineEdition') = 8))) THEN ', COMPRESSION' ELSE ', NO_COMPRESSION' END + END + + IF @Compress = 'Y' AND @CompressionAlgorithm IS NOT NULL + BEGIN + SET @CurrentCommand += ' (ALGORITHM = ' + @CompressionAlgorithm + ')' + END + + IF @CurrentBackupType = 'DIFF' SET @CurrentCommand += ', DIFFERENTIAL' + + IF EXISTS(SELECT * FROM @CurrentFiles WHERE Mirror = 1) + BEGIN + SET @CurrentCommand += ', FORMAT' + END + + IF @CopyOnly = 'Y' SET @CurrentCommand += ', COPY_ONLY' + IF @NoRecovery = 'Y' AND @CurrentBackupType = 'LOG' SET @CurrentCommand += ', NORECOVERY' + IF @Init = 'Y' SET @CurrentCommand += ', INIT' + IF @Format = 'Y' SET @CurrentCommand += ', FORMAT' + IF @BlockSize IS NOT NULL SET @CurrentCommand += ', BLOCKSIZE = ' + CAST(@BlockSize AS nvarchar) + IF @BufferCount IS NOT NULL SET @CurrentCommand += ', BUFFERCOUNT = ' + CAST(@BufferCount AS nvarchar) + IF @CurrentMaxTransferSize IS NOT NULL SET @CurrentCommand += ', MAXTRANSFERSIZE = ' + CAST(@CurrentMaxTransferSize AS nvarchar) + IF @Description IS NOT NULL SET @CurrentCommand += ', DESCRIPTION = N''' + REPLACE(@Description,'''','''''') + '''' + IF @BackupSetName IS NOT NULL SET @CurrentCommand += ', NAME = N''' + REPLACE(@BackupSetName,'''','''''') + '''' + IF @Stats IS NOT NULL SET @CurrentCommand += ', STATS = ' + CAST(@Stats AS nvarchar) + IF @BackupOptions IS NOT NULL SET @CurrentCommand += ', BACKUP_OPTIONS = N''' + REPLACE(@BackupOptions,'''','''''') + '''' + IF @Encrypt = 'Y' SET @CurrentCommand += ', ENCRYPTION (ALGORITHM = ' + UPPER(@EncryptionAlgorithm) + ', ' + IF @Encrypt = 'Y' AND @ServerCertificate IS NOT NULL SET @CurrentCommand += 'SERVER CERTIFICATE = ' + QUOTENAME(@ServerCertificate) + IF @Encrypt = 'Y' AND @ServerAsymmetricKey IS NOT NULL SET @CurrentCommand += 'SERVER ASYMMETRIC KEY = ' + QUOTENAME(@ServerAsymmetricKey) + IF @Encrypt = 'Y' SET @CurrentCommand += ')' + IF @URL IS NOT NULL AND @Credential IS NOT NULL SET @CurrentCommand += ', CREDENTIAL = N''' + REPLACE(@Credential,'''','''''') + '''' + IF @ExpireDate IS NOT NULL SET @CurrentCommand += ', EXPIREDATE = ''' + CONVERT(nvarchar, @ExpireDate, 21) + '''' + IF @RetainDays IS NOT NULL SET @CurrentCommand += ', RETAINDAYS = ' + CAST(@RetainDays AS nvarchar) + END + END IF @BackupSoftware = 'LITESPEED' BEGIN @@ -3773,8 +3901,8 @@ BEGIN END SET @CurrentCommand += ', @with = ''' - IF @CheckSum = 'Y' SET @CurrentCommand += 'CHECKSUM' - IF @CheckSum = 'N' SET @CurrentCommand += 'NO_CHECKSUM' + IF @Checksum = 'Y' SET @CurrentCommand += 'CHECKSUM' + IF @Checksum = 'N' SET @CurrentCommand += 'NO_CHECKSUM' IF @CurrentBackupType = 'DIFF' SET @CurrentCommand += ', DIFFERENTIAL' IF @CopyOnly = 'Y' SET @CurrentCommand += ', COPY_ONLY' IF @NoRecovery = 'Y' AND @CurrentBackupType = 'LOG' SET @CurrentCommand += ', NORECOVERY' @@ -3791,6 +3919,8 @@ BEGIN IF @Throttle IS NOT NULL SET @CurrentCommand += ', @throttle = ' + CAST(@Throttle AS nvarchar) IF @Description IS NOT NULL SET @CurrentCommand += ', @desc = N''' + REPLACE(@Description,'''','''''') + '''' IF @ObjectLevelRecoveryMap = 'Y' SET @CurrentCommand += ', @olrmap = 1' + IF @ExpireDate IS NOT NULL SET @CurrentCommand += ', @expiration = ''' + CONVERT(nvarchar, @ExpireDate, 21) + '''' + IF @RetainDays IS NOT NULL SET @CurrentCommand += ', @retaindays = ' + CAST(@RetainDays AS nvarchar) IF @EncryptionAlgorithm IS NOT NULL SET @CurrentCommand += ', @cryptlevel = ' + CASE WHEN @EncryptionAlgorithm = 'RC2_40' THEN '0' @@ -3835,8 +3965,8 @@ BEGIN SET @CurrentCommand += ' MIRRORFILE' + ' = N''' + REPLACE((SELECT FilePath FROM @CurrentFiles WHERE Mirror = 1),'''','''''') + ''', ' END - IF @CheckSum = 'Y' SET @CurrentCommand += 'CHECKSUM' - IF @CheckSum = 'N' SET @CurrentCommand += 'NO_CHECKSUM' + IF @Checksum = 'Y' SET @CurrentCommand += 'CHECKSUM' + IF @Checksum = 'N' SET @CurrentCommand += 'NO_CHECKSUM' IF @CurrentBackupType = 'DIFF' SET @CurrentCommand += ', DIFFERENTIAL' IF @CopyOnly = 'Y' SET @CurrentCommand += ', COPY_ONLY' IF @NoRecovery = 'Y' AND @CurrentBackupType = 'LOG' SET @CurrentCommand += ', NORECOVERY' @@ -3876,7 +4006,7 @@ BEGIN SET @CurrentCommand += ', @backuptype = ' + CASE WHEN @CurrentBackupType = 'FULL' THEN '''Full''' WHEN @CurrentBackupType = 'DIFF' THEN '''Differential''' WHEN @CurrentBackupType = 'LOG' THEN '''Log''' END IF @ReadWriteFileGroups = 'Y' AND @CurrentDatabaseName <> 'master' SET @CurrentCommand += ', @readwritefilegroups = 1' - SET @CurrentCommand += ', @checksum = ' + CASE WHEN @CheckSum = 'Y' THEN '1' WHEN @CheckSum = 'N' THEN '0' END + SET @CurrentCommand += ', @checksum = ' + CASE WHEN @Checksum = 'Y' THEN '1' WHEN @Checksum = 'N' THEN '0' END SET @CurrentCommand += ', @copyonly = ' + CASE WHEN @CopyOnly = 'Y' THEN '1' WHEN @CopyOnly = 'N' THEN '0' END IF @CompressionLevel IS NOT NULL SET @CurrentCommand += ', @compressionlevel = ' + CAST(@CompressionLevel AS nvarchar) IF @Threads IS NOT NULL SET @CurrentCommand += ', @threads = ' + CAST(@Threads AS nvarchar) @@ -3900,7 +4030,7 @@ BEGIN SET @CurrentCommand = 'DECLARE @ReturnCode int EXECUTE @ReturnCode = dbo.emc_run_backup ''' - SET @CurrentCommand += ' -c ' + CASE WHEN @CurrentAvailabilityGroup IS NOT NULL THEN @Cluster ELSE CAST(SERVERPROPERTY('MachineName') AS nvarchar) END + SET @CurrentCommand += ' -c ' + CASE WHEN @Cluster IS NOT NULL AND @CurrentAvailabilityGroup IS NOT NULL THEN @Cluster ELSE CAST(SERVERPROPERTY('MachineName') AS nvarchar) END SET @CurrentCommand += ' -l ' + CASE WHEN @CurrentBackupType = 'FULL' THEN 'full' @@ -3912,7 +4042,7 @@ BEGIN IF @CleanupTime IS NOT NULL SET @CurrentCommand += ' -y +' + CAST(@CleanupTime/24 + CASE WHEN @CleanupTime%24 > 0 THEN 1 ELSE 0 END AS nvarchar) + 'd' - IF @CheckSum = 'Y' SET @CurrentCommand += ' -k' + IF @Checksum = 'Y' SET @CurrentCommand += ' -k' SET @CurrentCommand += ' -S ' + CAST(@CurrentNumberOfFiles AS nvarchar) @@ -3929,9 +4059,11 @@ BEGIN SET @CurrentCommand += ' -a "NSR_SKIP_NON_BACKUPABLE_STATE_DB=TRUE"' SET @CurrentCommand += ' -a "BACKUP_PROMOTION=NONE"' IF @CopyOnly = 'Y' SET @CurrentCommand += ' -a "NSR_COPY_ONLY=TRUE"' + IF @BackupSetName IS NOT NULL SET @CurrentCommand += ' -N "' + REPLACE(@BackupSetName,'''','''''') + '"' - IF SERVERPROPERTY('InstanceName') IS NULL SET @CurrentCommand += ' "MSSQL' + ':' + REPLACE(REPLACE(@CurrentDatabaseName,'''',''''''),'.','\.') + '"' - IF SERVERPROPERTY('InstanceName') IS NOT NULL SET @CurrentCommand += ' "MSSQL$' + CAST(SERVERPROPERTY('InstanceName') AS nvarchar) + ':' + REPLACE(REPLACE(@CurrentDatabaseName,'''',''''''),'.','\.') + '"' + IF SERVERPROPERTY('InstanceName') IS NULL SET @CurrentCommand += ' "MSSQL' + IF SERVERPROPERTY('InstanceName') IS NOT NULL SET @CurrentCommand += ' "MSSQL$' + CAST(SERVERPROPERTY('InstanceName') AS nvarchar) + SET @CurrentCommand += ':' + REPLACE(REPLACE(@CurrentDatabaseName,'''',''''''),'.','\.') + '"' SET @CurrentCommand += '''' @@ -3979,8 +4111,9 @@ BEGIN ORDER BY FilePath ASC SET @CurrentCommand += ' WITH ' - IF @CheckSum = 'Y' SET @CurrentCommand += 'CHECKSUM' - IF @CheckSum = 'N' SET @CurrentCommand += 'NO_CHECKSUM' + IF @Checksum = 'Y' SET @CurrentCommand += 'CHECKSUM' + IF @Checksum = 'N' SET @CurrentCommand += 'NO_CHECKSUM' + IF @Stats IS NOT NULL SET @CurrentCommand += ', STATS = ' + CAST(@Stats AS nvarchar) IF @BackupOptions IS NOT NULL SET @CurrentCommand += ', RESTORE_OPTIONS = N''' + REPLACE(@BackupOptions,'''','''''') + '''' IF @URL IS NOT NULL AND @Credential IS NOT NULL SET @CurrentCommand += ', CREDENTIAL = N''' + REPLACE(@Credential,'''','''''') + '''' END @@ -3999,8 +4132,8 @@ BEGIN ORDER BY FilePath ASC SET @CurrentCommand += ', @with = ''' - IF @CheckSum = 'Y' SET @CurrentCommand += 'CHECKSUM' - IF @CheckSum = 'N' SET @CurrentCommand += 'NO_CHECKSUM' + IF @Checksum = 'Y' SET @CurrentCommand += 'CHECKSUM' + IF @Checksum = 'N' SET @CurrentCommand += 'NO_CHECKSUM' SET @CurrentCommand += '''' IF @EncryptionKey IS NOT NULL SET @CurrentCommand += ', @encryptionkey = N''' + REPLACE(@EncryptionKey,'''','''''') + '''' @@ -4021,8 +4154,8 @@ BEGIN ORDER BY FilePath ASC SET @CurrentCommand += ' WITH ' - IF @CheckSum = 'Y' SET @CurrentCommand += 'CHECKSUM' - IF @CheckSum = 'N' SET @CurrentCommand += 'NO_CHECKSUM' + IF @Checksum = 'Y' SET @CurrentCommand += 'CHECKSUM' + IF @Checksum = 'N' SET @CurrentCommand += 'NO_CHECKSUM' IF @EncryptionKey IS NOT NULL SET @CurrentCommand += ', PASSWORD = N''' + REPLACE(@EncryptionKey,'''','''''') + '''' SET @CurrentCommand = 'DECLARE @ReturnCode int EXECUTE @ReturnCode = dbo.sqlbackup N''-SQL "' + REPLACE(@CurrentCommand,'''','''''') + '"''' + ' IF @ReturnCode <> 0 RAISERROR(''Error verifying SQLBackup backup.'', 16, 1)' @@ -4223,6 +4356,7 @@ BEGIN SET @CurrentDifferentialBaseLSN = NULL SET @CurrentDifferentialBaseIsSnapshot = NULL SET @CurrentLogLSN = NULL + SET @BackupInProcess = NULL SET @CurrentLatestBackup = NULL SET @CurrentDatabaseNameFS = NULL SET @CurrentDirectoryStructure = NULL @@ -4278,4 +4412,4 @@ BEGIN ---------------------------------------------------------------------------------------------------- END -GO \ No newline at end of file +GO \ No newline at end of file diff --git a/DatabaseIntegrityCheck.sql b/DatabaseIntegrityCheck.sql index 17f5daa..e01b56e 100644 --- a/DatabaseIntegrityCheck.sql +++ b/DatabaseIntegrityCheck.sql @@ -15,6 +15,7 @@ ALTER PROCEDURE [dbo].[DatabaseIntegrityCheck] @DataPurity nvarchar(max) = 'N', @NoIndex nvarchar(max) = 'N', @ExtendedLogicalChecks nvarchar(max) = 'N', +@NoInformationalMessages nvarchar(max) = 'N', @TabLock nvarchar(max) = 'N', @FileGroups nvarchar(max) = NULL, @Objects nvarchar(max) = NULL, @@ -39,7 +40,7 @@ BEGIN --// Source: https://ola.hallengren.com //-- --// License: https://ola.hallengren.com/license.html //-- --// GitHub: https://github.com/olahallengren/sql-server-maintenance-solution //-- - --// Version: 2024-12-27 18:10:28 //-- + --// Version: 2025-02-19 21:12:35 //-- ---------------------------------------------------------------------------------------------------- SET NOCOUNT ON @@ -191,7 +192,7 @@ BEGIN SET @HostPlatform = 'Windows' END - DECLARE @AmazonRDS bit = CASE WHEN DB_ID('rdsadmin') IS NOT NULL AND SUSER_SNAME(0x01) = 'rdsa' THEN 1 ELSE 0 END + DECLARE @AmazonRDS bit = CASE WHEN SERVERPROPERTY('EngineEdition') IN (5, 8) THEN 0 WHEN EXISTS (SELECT * FROM sys.databases WHERE [name] = 'rdsadmin') AND SUSER_SNAME(0x01) = 'rdsa' THEN 1 ELSE 0 END ---------------------------------------------------------------------------------------------------- --// Log initial information //-- @@ -203,6 +204,7 @@ BEGIN SET @Parameters += ', @DataPurity = ' + ISNULL('''' + REPLACE(@DataPurity,'''','''''') + '''','NULL') SET @Parameters += ', @NoIndex = ' + ISNULL('''' + REPLACE(@NoIndex,'''','''''') + '''','NULL') SET @Parameters += ', @ExtendedLogicalChecks = ' + ISNULL('''' + REPLACE(@ExtendedLogicalChecks,'''','''''') + '''','NULL') + SET @Parameters += ', @NoInformationalMessages = ' + ISNULL('''' + REPLACE(@NoInformationalMessages,'''','''''') + '''','NULL') SET @Parameters += ', @TabLock = ' + ISNULL('''' + REPLACE(@TabLock,'''','''''') + '''','NULL') SET @Parameters += ', @FileGroups = ' + ISNULL('''' + REPLACE(@FileGroups,'''','''''') + '''','NULL') SET @Parameters += ', @Objects = ' + ISNULL('''' + REPLACE(@Objects,'''','''''') + '''','NULL') @@ -234,7 +236,7 @@ BEGIN SET @StartMessage = 'Platform: ' + @HostPlatform RAISERROR('%s',10,1,@StartMessage) WITH NOWAIT - SET @StartMessage = 'Procedure: ' + QUOTENAME(DB_NAME(DB_ID())) + '.' + QUOTENAME(@SchemaName) + '.' + QUOTENAME(@ObjectName) + SET @StartMessage = 'Procedure: ' + QUOTENAME(DB_NAME()) + '.' + QUOTENAME(@SchemaName) + '.' + QUOTENAME(@ObjectName) RAISERROR('%s',10,1,@StartMessage) WITH NOWAIT SET @StartMessage = 'Parameters: ' + @Parameters @@ -252,10 +254,10 @@ BEGIN --// Check core requirements //-- ---------------------------------------------------------------------------------------------------- - IF NOT (SELECT [compatibility_level] FROM sys.databases WHERE database_id = DB_ID()) >= 90 + IF NOT (SELECT [compatibility_level] FROM sys.databases WHERE [name] = DB_NAME()) >= 90 BEGIN INSERT INTO @Errors ([Message], Severity, [State]) - SELECT 'The database ' + QUOTENAME(DB_NAME(DB_ID())) + ' has to be in compatibility level 90 or higher.', 16, 1 + SELECT 'The database ' + QUOTENAME(DB_NAME()) + ' has to be in compatibility level 90 or higher.', 16, 1 END IF NOT (SELECT uses_ansi_nulls FROM sys.sql_modules WHERE [object_id] = @@PROCID) = 1 @@ -750,6 +752,13 @@ BEGIN ---------------------------------------------------------------------------------------------------- + IF @NoInformationalMessages NOT IN ('Y','N') OR @NoInformationalMessages IS NULL + BEGIN + INSERT INTO @Errors ([Message], Severity, [State]) + SELECT 'The value for the parameter @NoInformationalMessages is not supported.', 16, 1 + END + + ---------------------------------------------------------------------------------------------------- IF @TabLock NOT IN ('Y','N') OR @TabLock IS NULL BEGIN INSERT INTO @Errors ([Message], Severity, [State]) @@ -1355,8 +1364,8 @@ BEGIN SET @DatabaseMessage = 'Recovery model: ' + @CurrentRecoveryModel RAISERROR('%s',10,1,@DatabaseMessage) WITH NOWAIT END - - IF @Version >= 11 AND SERVERPROPERTY('IsHadrEnabled') = 1 + + IF @Version >= 11 AND SERVERPROPERTY('IsHadrEnabled') = 1 BEGIN SELECT @CurrentReplicaID = databases.replica_id FROM sys.databases databases @@ -1386,11 +1395,12 @@ BEGIN IF SERVERPROPERTY('EngineEdition') <> 5 BEGIN SELECT @CurrentDatabaseMirroringRole = UPPER(mirroring_role_desc) - FROM sys.database_mirroring - WHERE database_id = DB_ID(@CurrentDatabaseName) + FROM sys.database_mirroring database_mirroring + INNER JOIN sys.databases databases ON database_mirroring.database_id = databases.database_id + WHERE databases.[name] = @CurrentDatabaseName END - - IF @CurrentAvailabilityGroup IS NOT NULL + + IF @CurrentAvailabilityGroup IS NOT NULL BEGIN SET @DatabaseMessage = 'Availability group: ' + ISNULL(@CurrentAvailabilityGroup,'N/A') RAISERROR('%s',10,1,@DatabaseMessage) WITH NOWAIT @@ -1428,6 +1438,7 @@ BEGIN AND ((@AvailabilityGroupReplicas = 'PRIMARY' AND @CurrentAvailabilityGroupRole = 'PRIMARY') OR (@AvailabilityGroupReplicas = 'SECONDARY' AND @CurrentAvailabilityGroupRole = 'SECONDARY') OR (@AvailabilityGroupReplicas = 'PREFERRED_BACKUP_REPLICA' AND @CurrentIsPreferredBackupReplica = 1) OR @AvailabilityGroupReplicas = 'ALL' OR @CurrentAvailabilityGroupRole IS NULL) AND NOT (@CurrentIsReadOnly = 1 AND @Updateability = 'READ_WRITE') AND NOT (@CurrentIsReadOnly = 0 AND @Updateability = 'READ_ONLY') + AND NOT (@AmazonRDS = 1 AND @CurrentDatabaseName = 'rdsadmin') BEGIN -- Check database @@ -1441,10 +1452,11 @@ BEGIN IF @LockTimeout IS NOT NULL SET @CurrentCommand = 'SET LOCK_TIMEOUT ' + CAST(@LockTimeout * 1000 AS nvarchar) + '; ' SET @CurrentCommand += 'DBCC CHECKDB (' + QUOTENAME(@CurrentDatabaseName) IF @NoIndex = 'Y' SET @CurrentCommand += ', NOINDEX' - SET @CurrentCommand += ') WITH NO_INFOMSGS, ALL_ERRORMSGS' + SET @CurrentCommand += ') WITH ALL_ERRORMSGS' IF @DataPurity = 'Y' SET @CurrentCommand += ', DATA_PURITY' IF @PhysicalOnly = 'Y' SET @CurrentCommand += ', PHYSICAL_ONLY' IF @ExtendedLogicalChecks = 'Y' SET @CurrentCommand += ', EXTENDED_LOGICAL_CHECKS' + IF @NoInformationalMessages = 'Y' SET @CurrentCommand += ', NO_INFOMSGS' IF @TabLock = 'Y' SET @CurrentCommand += ', TABLOCK' IF @MaxDOP IS NOT NULL SET @CurrentCommand += ', MAXDOP = ' + CAST(@MaxDOP AS nvarchar) @@ -1569,8 +1581,9 @@ BEGIN IF @LockTimeout IS NOT NULL SET @CurrentCommand = 'SET LOCK_TIMEOUT ' + CAST(@LockTimeout * 1000 AS nvarchar) + '; ' SET @CurrentCommand += 'DBCC CHECKFILEGROUP (' + QUOTENAME(@CurrentFileGroupName) IF @NoIndex = 'Y' SET @CurrentCommand += ', NOINDEX' - SET @CurrentCommand += ') WITH NO_INFOMSGS, ALL_ERRORMSGS' + SET @CurrentCommand += ') WITH ALL_ERRORMSGS' IF @PhysicalOnly = 'Y' SET @CurrentCommand += ', PHYSICAL_ONLY' + IF @NoInformationalMessages = 'Y' SET @CurrentCommand += ', NO_INFOMSGS' IF @TabLock = 'Y' SET @CurrentCommand += ', TABLOCK' IF @MaxDOP IS NOT NULL SET @CurrentCommand += ', MAXDOP = ' + CAST(@MaxDOP AS nvarchar) @@ -1608,7 +1621,8 @@ BEGIN SET @CurrentCommand = '' IF @LockTimeout IS NOT NULL SET @CurrentCommand = 'SET LOCK_TIMEOUT ' + CAST(@LockTimeout * 1000 AS nvarchar) + '; ' SET @CurrentCommand += 'DBCC CHECKALLOC (' + QUOTENAME(@CurrentDatabaseName) - SET @CurrentCommand += ') WITH NO_INFOMSGS, ALL_ERRORMSGS' + SET @CurrentCommand += ') WITH ALL_ERRORMSGS' + IF @NoInformationalMessages = 'Y' SET @CurrentCommand += ', NO_INFOMSGS' IF @TabLock = 'Y' SET @CurrentCommand += ', TABLOCK' EXECUTE @CurrentCommandOutput = dbo.CommandExecute @DatabaseContext = @CurrentDatabaseContext, @Command = @CurrentCommand, @CommandType = @CurrentCommandType, @Mode = 1, @DatabaseName = @CurrentDatabaseName, @LogToTable = @LogToTable, @Execute = @Execute @@ -1736,10 +1750,11 @@ BEGIN IF @LockTimeout IS NOT NULL SET @CurrentCommand = 'SET LOCK_TIMEOUT ' + CAST(@LockTimeout * 1000 AS nvarchar) + '; ' SET @CurrentCommand += 'DBCC CHECKTABLE (' + QUOTENAME(QUOTENAME(@CurrentSchemaName) + '.' + QUOTENAME(@CurrentObjectName),'''') IF @NoIndex = 'Y' SET @CurrentCommand += ', NOINDEX' - SET @CurrentCommand += ') WITH NO_INFOMSGS, ALL_ERRORMSGS' + SET @CurrentCommand += ') WITH ALL_ERRORMSGS' IF @DataPurity = 'Y' SET @CurrentCommand += ', DATA_PURITY' IF @PhysicalOnly = 'Y' SET @CurrentCommand += ', PHYSICAL_ONLY' IF @ExtendedLogicalChecks = 'Y' SET @CurrentCommand += ', EXTENDED_LOGICAL_CHECKS' + IF @NoInformationalMessages = 'Y' SET @CurrentCommand += ', NO_INFOMSGS' IF @TabLock = 'Y' SET @CurrentCommand += ', TABLOCK' IF @MaxDOP IS NOT NULL SET @CurrentCommand += ', MAXDOP = ' + CAST(@MaxDOP AS nvarchar) @@ -1780,7 +1795,8 @@ BEGIN SET @CurrentCommand = '' IF @LockTimeout IS NOT NULL SET @CurrentCommand = 'SET LOCK_TIMEOUT ' + CAST(@LockTimeout * 1000 AS nvarchar) + '; ' SET @CurrentCommand += 'DBCC CHECKCATALOG (' + QUOTENAME(@CurrentDatabaseName) - SET @CurrentCommand += ') WITH NO_INFOMSGS' + SET @CurrentCommand += ')' + IF @NoInformationalMessages = 'Y' SET @CurrentCommand += ' WITH NO_INFOMSGS' EXECUTE @CurrentCommandOutput = dbo.CommandExecute @DatabaseContext = @CurrentDatabaseContext, @Command = @CurrentCommand, @CommandType = @CurrentCommandType, @Mode = 1, @DatabaseName = @CurrentDatabaseName, @LogToTable = @LogToTable, @Execute = @Execute SET @Error = @@ERROR @@ -1865,5 +1881,12 @@ BEGIN END +GO + END + + ---------------------------------------------------------------------------------------------------- + +END + GO diff --git a/IndexOptimize.sql b/IndexOptimize.sql index b34626c..71b7e0c 100644 --- a/IndexOptimize.sql +++ b/IndexOptimize.sql @@ -2,6 +2,10 @@ GO SET QUOTED_IDENTIFIER ON GO +SET ANSI_NULLS ON +GO +SET QUOTED_IDENTIFIER ON +GO IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[IndexOptimize]') AND type in (N'P', N'PC')) BEGIN EXEC dbo.sp_executesql @statement = N'CREATE PROCEDURE [dbo].[IndexOptimize] AS' @@ -53,7 +57,7 @@ BEGIN --// Source: https://ola.hallengren.com //-- --// License: https://ola.hallengren.com/license.html //-- --// GitHub: https://github.com/olahallengren/sql-server-maintenance-solution //-- - --// Version: 2024-12-27 18:10:28 //-- + --// Version: 2025-02-19 21:12:35 //-- ---------------------------------------------------------------------------------------------------- SET NOCOUNT ON @@ -137,10 +141,12 @@ BEGIN DECLARE @CurrentIsImageText bit DECLARE @CurrentIsNewLOB bit DECLARE @CurrentIsFileStream bit - DECLARE @CurrentIsColumnStore bit + DECLARE @CurrentHasColumnstore bit DECLARE @CurrentIsComputed bit + DECLARE @CurrentIsClusteredIndexComputed bit DECLARE @CurrentIsTimestamp bit DECLARE @CurrentAllowPageLocks bit + DECLARE @CurrentHasFilter bit DECLARE @CurrentNoRecompute bit DECLARE @CurrentIsIncremental bit DECLARE @CurrentRowCount bigint @@ -187,11 +193,13 @@ BEGIN IndexName nvarchar(max), IndexType int, AllowPageLocks bit, + HasFilter bit, IsImageText bit, IsNewLOB bit, IsFileStream bit, - IsColumnStore bit, + HasColumnstore bit, IsComputed bit, + IsClusteredIndexComputed bit, IsTimestamp bit, OnReadOnlyFileGroup bit, ResumableIndexOperation bit, @@ -270,7 +278,7 @@ BEGIN SET @HostPlatform = 'Windows' END - DECLARE @AmazonRDS bit = CASE WHEN DB_ID('rdsadmin') IS NOT NULL AND SUSER_SNAME(0x01) = 'rdsa' THEN 1 ELSE 0 END + DECLARE @AmazonRDS bit = CASE WHEN SERVERPROPERTY('EngineEdition') IN (5, 8) THEN 0 WHEN EXISTS (SELECT * FROM sys.databases WHERE [name] = 'rdsadmin') AND SUSER_SNAME(0x01) = 'rdsa' THEN 1 ELSE 0 END ---------------------------------------------------------------------------------------------------- --// Log initial information //-- @@ -327,7 +335,7 @@ BEGIN SET @StartMessage = 'Platform: ' + @HostPlatform RAISERROR('%s',10,1,@StartMessage) WITH NOWAIT - SET @StartMessage = 'Procedure: ' + QUOTENAME(DB_NAME(DB_ID())) + '.' + QUOTENAME(@SchemaName) + '.' + QUOTENAME(@ObjectName) + SET @StartMessage = 'Procedure: ' + QUOTENAME(DB_NAME()) + '.' + QUOTENAME(@SchemaName) + '.' + QUOTENAME(@ObjectName) RAISERROR('%s',10,1,@StartMessage) WITH NOWAIT SET @StartMessage = 'Parameters: ' + @Parameters @@ -345,10 +353,10 @@ BEGIN --// Check core requirements //-- ---------------------------------------------------------------------------------------------------- - IF NOT (SELECT [compatibility_level] FROM sys.databases WHERE database_id = DB_ID()) >= 90 + IF NOT (SELECT [compatibility_level] FROM sys.databases WHERE [name] = DB_NAME()) >= 90 BEGIN INSERT INTO @Errors ([Message], Severity, [State]) - SELECT 'The database ' + QUOTENAME(DB_NAME(DB_ID())) + ' has to be in compatibility level 90 or higher.', 16, 1 + SELECT 'The database ' + QUOTENAME(DB_NAME()) + ' has to be in compatibility level 90 or higher.', 16, 1 END IF NOT (SELECT uses_ansi_nulls FROM sys.sql_modules WHERE [object_id] = @@PROCID) = 1 @@ -1429,15 +1437,15 @@ BEGIN SET @CurrentDatabase_sp_executesql = QUOTENAME(@CurrentDatabaseName) + '.sys.sp_executesql' - IF @ExecuteAsUser IS NOT NULL + BEGIN - SET @CurrentCommand = '' - SET @CurrentCommand += 'IF EXISTS(SELECT * FROM sys.database_principals database_principals WHERE database_principals.[name] = @ParamExecuteAsUser) BEGIN SET @ParamExecuteAsUserExists = 1 END ELSE BEGIN SET @ParamExecuteAsUserExists = 0 END' + + - EXECUTE @CurrentDatabase_sp_executesql @stmt = @CurrentCommand, @params = N'@ParamExecuteAsUser sysname, @ParamExecuteAsUserExists bit OUTPUT', @ParamExecuteAsUser = @ExecuteAsUser, @ParamExecuteAsUserExists = @CurrentExecuteAsUserExists OUTPUT - END + + - BEGIN + SET @DatabaseMessage = 'Date and time: ' + CONVERT(nvarchar,SYSDATETIME(),120) RAISERROR('%s',10,1,@DatabaseMessage) WITH NOWAIT @@ -1493,8 +1501,9 @@ BEGIN IF SERVERPROPERTY('EngineEdition') <> 5 BEGIN SELECT @CurrentDatabaseMirroringRole = UPPER(mirroring_role_desc) - FROM sys.database_mirroring - WHERE database_id = DB_ID(@CurrentDatabaseName) + FROM sys.database_mirroring database_mirroring + INNER JOIN sys.databases databases ON database_mirroring.database_id = databases.database_id + WHERE databases.[name] = @CurrentDatabaseName END IF @CurrentAvailabilityGroup IS NOT NULL @@ -1513,7 +1522,17 @@ BEGIN END RAISERROR(@EmptyLine,10,1) WITH NOWAIT + IF @ExecuteAsUser IS NOT NULL + AND @CurrentDatabaseState = 'ONLINE' + AND NOT (@CurrentUserAccess = 'SINGLE_USER') + AND NOT (@CurrentAvailabilityGroup IS NOT NULL AND (@CurrentAvailabilityGroupRole <> 'PRIMARY' OR @CurrentAvailabilityGroupRole IS NULL)) + AND NOT (@AmazonRDS = 1 AND @CurrentDatabaseName = 'rdsadmin') + BEGIN + SET @CurrentCommand = '' + SET @CurrentCommand += 'IF EXISTS(SELECT * FROM sys.database_principals database_principals WHERE database_principals.[name] = @ParamExecuteAsUser) BEGIN SET @ParamExecuteAsUserExists = 1 END ELSE BEGIN SET @ParamExecuteAsUserExists = 0 END' + EXECUTE @CurrentDatabase_sp_executesql @stmt = @CurrentCommand, @params = N'@ParamExecuteAsUser sysname, @ParamExecuteAsUserExists bit OUTPUT', @ParamExecuteAsUser = @ExecuteAsUser, @ParamExecuteAsUserExists = @CurrentExecuteAsUserExists OUTPUT + END IF @CurrentExecuteAsUserExists = 0 BEGIN SET @DatabaseMessage = 'The user ' + QUOTENAME(@ExecuteAsUser) + ' does not exist in the database ' + QUOTENAME(@CurrentDatabaseName) + '.' @@ -1524,6 +1543,8 @@ BEGIN IF @CurrentDatabaseState = 'ONLINE' AND NOT (@CurrentUserAccess = 'SINGLE_USER') AND NOT (@CurrentAvailabilityGroup IS NOT NULL AND (@CurrentAvailabilityGroupRole <> 'PRIMARY' OR @CurrentAvailabilityGroupRole IS NULL)) + AND NOT (@AmazonRDS = 1 AND @CurrentDatabaseName = 'rdsadmin') + AND NOT (@CurrentIsReadOnly = 1) AND (@CurrentExecuteAsUserExists = 1 OR @CurrentExecuteAsUserExists IS NULL) BEGIN @@ -1531,7 +1552,7 @@ BEGIN IF (EXISTS(SELECT * FROM @ActionsPreferred) OR @UpdateStatistics IS NOT NULL) AND (SYSDATETIME() < DATEADD(SECOND,@TimeLimit,@StartTime) OR @TimeLimit IS NULL) BEGIN SET @CurrentCommand = 'SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;' - + ' SELECT SchemaID, SchemaName, ObjectID, ObjectName, ObjectType, IsMemoryOptimized, IndexID, IndexName, IndexType, AllowPageLocks, IsImageText, IsNewLOB, IsFileStream, IsColumnStore, IsComputed, IsTimestamp, OnReadOnlyFileGroup, ResumableIndexOperation, StatisticsID, StatisticsName, NoRecompute, IsIncremental, PartitionID, PartitionNumber, PartitionCount, [Order], Selected, Completed' + + ' SELECT SchemaID, SchemaName, ObjectID, ObjectName, ObjectType, IsMemoryOptimized, IndexID, IndexName, IndexType, AllowPageLocks, HasFilter, IsImageText, IsNewLOB, IsFileStream, HasColumnstore, IsComputed, IsClusteredIndexComputed, IsTimestamp, OnReadOnlyFileGroup, ResumableIndexOperation, StatisticsID, StatisticsName, NoRecompute, IsIncremental, PartitionID, PartitionNumber, PartitionCount, [Order], Selected, Completed' + ' FROM (' IF EXISTS(SELECT * FROM @ActionsPreferred) OR @UpdateStatistics IN('ALL','INDEX') @@ -1546,6 +1567,7 @@ BEGIN + ', indexes.[name] AS IndexName' + ', indexes.[type] AS IndexType' + ', indexes.allow_page_locks AS AllowPageLocks' + + ', indexes.has_filter AS HasFilter' + ', CASE WHEN indexes.[type] = 1 AND EXISTS(SELECT * FROM sys.columns columns INNER JOIN sys.types types ON columns.system_type_id = types.user_type_id WHERE columns.[object_id] = objects.object_id AND types.name IN(''image'',''text'',''ntext'')) THEN 1 ELSE 0 END AS IsImageText' @@ -1554,17 +1576,18 @@ BEGIN + ', CASE WHEN indexes.[type] = 1 AND EXISTS(SELECT * FROM sys.columns columns WHERE columns.[object_id] = objects.object_id AND columns.is_filestream = 1) THEN 1 ELSE 0 END AS IsFileStream' - + ', CASE WHEN EXISTS(SELECT * FROM sys.indexes indexes WHERE indexes.[object_id] = objects.object_id AND [type] IN(5,6)) THEN 1 ELSE 0 END AS IsColumnStore' + + ', CASE WHEN EXISTS(SELECT * FROM sys.indexes indexes WHERE indexes.[object_id] = objects.object_id AND [type] IN(5,6)) THEN 1 ELSE 0 END AS HasColumnstore' + ', CASE WHEN EXISTS(SELECT * FROM sys.index_columns index_columns INNER JOIN sys.columns columns ON index_columns.object_id = columns.object_id AND index_columns.column_id = columns.column_id WHERE (index_columns.key_ordinal > 0 OR index_columns.partition_ordinal > 0) AND columns.is_computed = 1 AND index_columns.object_id = indexes.object_id AND index_columns.index_id = indexes.index_id) THEN 1 ELSE 0 END AS IsComputed' + + ', CASE WHEN EXISTS(SELECT * FROM sys.index_columns index_columns INNER JOIN sys.columns columns ON index_columns.object_id = columns.object_id AND index_columns.column_id = columns.column_id INNER JOIN sys.indexes indexes2 ON index_columns.object_id = indexes2.object_id AND index_columns.index_id = indexes2.index_id WHERE (index_columns.key_ordinal > 0 OR index_columns.partition_ordinal > 0) AND columns.is_computed = 1 AND indexes2.[type] = 1 AND index_columns.object_id = indexes.object_id) THEN 1 ELSE 0 END AS IsClusteredIndexComputed' + ', CASE WHEN EXISTS(SELECT * FROM sys.index_columns index_columns INNER JOIN sys.columns columns ON index_columns.[object_id] = columns.[object_id] AND index_columns.column_id = columns.column_id INNER JOIN sys.types types ON columns.system_type_id = types.system_type_id WHERE index_columns.[object_id] = objects.object_id AND index_columns.index_id = indexes.index_id AND types.[name] = ''timestamp'') THEN 1 ELSE 0 END AS IsTimestamp' + ', CASE WHEN EXISTS (SELECT * FROM sys.indexes indexes2 INNER JOIN sys.destination_data_spaces destination_data_spaces ON indexes.data_space_id = destination_data_spaces.partition_scheme_id INNER JOIN sys.filegroups filegroups ON destination_data_spaces.data_space_id = filegroups.data_space_id WHERE filegroups.is_read_only = 1 AND indexes2.[object_id] = indexes.[object_id] AND indexes2.[index_id] = indexes.index_id' + CASE WHEN @PartitionLevel = 'Y' THEN ' AND destination_data_spaces.destination_id = partitions.partition_number' ELSE '' END + ') THEN 1' + ' WHEN EXISTS (SELECT * FROM sys.indexes indexes2 INNER JOIN sys.filegroups filegroups ON indexes.data_space_id = filegroups.data_space_id WHERE filegroups.is_read_only = 1 AND indexes.[object_id] = indexes2.[object_id] AND indexes.[index_id] = indexes2.index_id) THEN 1' + ' WHEN indexes.[type] = 1 AND EXISTS (SELECT * FROM sys.tables tables INNER JOIN sys.filegroups filegroups ON tables.lob_data_space_id = filegroups.data_space_id WHERE filegroups.is_read_only = 1 AND tables.[object_id] = objects.[object_id]) THEN 1 ELSE 0 END AS OnReadOnlyFileGroup' - + ', ' + CASE WHEN @Version >= 14 THEN 'CASE WHEN EXISTS(SELECT * FROM sys.index_resumable_operations index_resumable_operations WHERE state_desc = ''PAUSED'' AND index_resumable_operations.object_id = indexes.object_id AND index_resumable_operations.index_id = indexes.index_id AND (index_resumable_operations.partition_number = partitions.partition_number OR index_resumable_operations.partition_number IS NULL)) THEN 1 ELSE 0 END' ELSE '0' END + ' AS ResumableIndexOperation' + + ', ' + CASE WHEN @Version >= 14 OR SERVERPROPERTY('EngineEdition') IN (5, 8) THEN 'CASE WHEN EXISTS(SELECT * FROM sys.index_resumable_operations index_resumable_operations WHERE state_desc = ''PAUSED'' AND index_resumable_operations.object_id = indexes.object_id AND index_resumable_operations.index_id = indexes.index_id' + CASE WHEN @PartitionLevel = 'Y' THEN ' AND (index_resumable_operations.partition_number = partitions.partition_number OR index_resumable_operations.partition_number IS NULL)' ELSE '' END + ') THEN 1 ELSE 0 END' ELSE '0' END + ' AS ResumableIndexOperation' + ', stats.stats_id AS StatisticsID' + ', stats.name AS StatisticsName' @@ -1609,11 +1632,13 @@ BEGIN + ', NULL AS IndexID, NULL AS IndexName' + ', NULL AS IndexType' + ', NULL AS AllowPageLocks' + + ', NULL AS HasFilter' + ', NULL AS IsImageText' + ', NULL AS IsNewLOB' + ', NULL AS IsFileStream' - + ', NULL AS IsColumnStore' + + ', NULL AS HasColumnstore' + ', NULL AS IsComputed' + + ', NULL AS IsClusteredIndexComputed' + ', NULL AS IsTimestamp' + ', NULL AS OnReadOnlyFileGroup' + ', NULL AS ResumableIndexOperation' @@ -1638,13 +1663,59 @@ BEGIN END SET @CurrentCommand = @CurrentCommand + ' WHERE objects.[type] IN(''U'',''V'')' + + CASE WHEN @Version >= 12 THEN ' AND (tables.is_memory_optimized = 0 OR tables.is_memory_optimized IS NULL)' ELSE '' END + CASE WHEN @MSShippedObjects = 'N' THEN ' AND objects.is_ms_shipped = 0' ELSE '' END + ' AND NOT EXISTS(SELECT * FROM sys.indexes indexes WHERE indexes.[object_id] = stats.[object_id] AND indexes.index_id = stats.stats_id)' + + ' AND NOT EXISTS(SELECT * FROM sys.indexes indexes2 WHERE indexes2.[object_id] = stats.[object_id] AND indexes2.type = 1 AND indexes2.is_disabled = 1)' + + IF @Version >= 12 + BEGIN + SET @CurrentCommand = @CurrentCommand + ' UNION ' + + SET @CurrentCommand = @CurrentCommand + 'SELECT schemas.[schema_id] AS SchemaID' + + ', schemas.[name] AS SchemaName' + + ', objects.[object_id] AS ObjectID' + + ', objects.[name] AS ObjectName' + + ', RTRIM(objects.[type]) AS ObjectType' + + ', tables.is_memory_optimized AS IsMemoryOptimized' + + ', NULL AS IndexID, NULL AS IndexName' + + ', NULL AS IndexType' + + ', NULL AS AllowPageLocks' + + ', NULL AS HasFilter' + + ', NULL AS IsImageText' + + ', NULL AS IsNewLOB' + + ', NULL AS IsFileStream' + + ', NULL AS HasColumnstore' + + ', NULL AS IsComputed' + + ', NULL AS IsClusteredIndexComputed' + + ', NULL AS IsTimestamp' + + ', NULL AS OnReadOnlyFileGroup' + + ', NULL AS ResumableIndexOperation' + + ', stats.stats_id AS StatisticsID' + + ', stats.name AS StatisticsName' + + ', stats.no_recompute AS NoRecompute' + + ', ' + CASE WHEN @Version >= 12 THEN 'stats.is_incremental' ELSE '0' END + ' AS IsIncremental' + + ', NULL AS PartitionID' + + ', NULL AS PartitionNumber' + + ', NULL AS PartitionCount' + + ', 0 AS [Order]' + + ', 0 AS Selected' + + ', 0 AS Completed' + + ' FROM sys.stats stats' + + ' INNER JOIN sys.objects objects ON stats.[object_id] = objects.[object_id]' + + ' INNER JOIN sys.schemas schemas ON objects.[schema_id] = schemas.[schema_id]' + + ' INNER JOIN sys.tables tables ON objects.[object_id] = tables.[object_id]' + + SET @CurrentCommand = @CurrentCommand + ' WHERE objects.[type] = ''U''' + + ' AND tables.is_memory_optimized = 1' + + CASE WHEN @MSShippedObjects = 'N' THEN ' AND objects.is_ms_shipped = 0' ELSE '' END + + ' AND NOT EXISTS(SELECT * FROM sys.indexes indexes WHERE indexes.[object_id] = stats.[object_id] AND indexes.index_id = stats.stats_id)' + END END SET @CurrentCommand = @CurrentCommand + ') IndexesStatistics' - INSERT INTO @tmpIndexesStatistics (SchemaID, SchemaName, ObjectID, ObjectName, ObjectType, IsMemoryOptimized, IndexID, IndexName, IndexType, AllowPageLocks, IsImageText, IsNewLOB, IsFileStream, IsColumnStore, IsComputed, IsTimestamp, OnReadOnlyFileGroup, ResumableIndexOperation, StatisticsID, StatisticsName, [NoRecompute], IsIncremental, PartitionID, PartitionNumber, PartitionCount, [Order], Selected, Completed) + INSERT INTO @tmpIndexesStatistics (SchemaID, SchemaName, ObjectID, ObjectName, ObjectType, IsMemoryOptimized, IndexID, IndexName, IndexType, AllowPageLocks, HasFilter, IsImageText, IsNewLOB, IsFileStream, HasColumnstore, IsComputed, IsClusteredIndexComputed, IsTimestamp, OnReadOnlyFileGroup, ResumableIndexOperation, StatisticsID, StatisticsName, [NoRecompute], IsIncremental, PartitionID, PartitionNumber, PartitionCount, [Order], Selected, Completed) EXECUTE @CurrentDatabase_sp_executesql @stmt = @CurrentCommand SET @Error = @@ERROR IF @Error <> 0 @@ -1744,11 +1815,13 @@ BEGIN @CurrentIndexName = IndexName, @CurrentIndexType = IndexType, @CurrentAllowPageLocks = AllowPageLocks, + @CurrentHasFilter = HasFilter, @CurrentIsImageText = IsImageText, @CurrentIsNewLOB = IsNewLOB, @CurrentIsFileStream = IsFileStream, - @CurrentIsColumnStore = IsColumnStore, + @CurrentHasColumnstore = HasColumnstore, @CurrentIsComputed = IsComputed, + @CurrentIsClusteredIndexComputed = IsClusteredIndexComputed, @CurrentIsTimestamp = IsTimestamp, @CurrentOnReadOnlyFileGroup = OnReadOnlyFileGroup, @CurrentResumableIndexOperation = ResumableIndexOperation, @@ -1886,6 +1959,7 @@ BEGIN AND @CurrentOnReadOnlyFileGroup = 0 AND EXISTS(SELECT * FROM @ActionsPreferred) AND (EXISTS(SELECT [Priority], [Action], COUNT(*) FROM @ActionsPreferred GROUP BY [Priority], [Action] HAVING COUNT(*) <> 3) OR @MinNumberOfPages > 0 OR @MaxNumberOfPages IS NOT NULL) + AND NOT (SERVERPROPERTY('EngineEdition') = 8 AND @CurrentDatabaseName IN ('master', 'model')) BEGIN SET @CurrentCommand = '' @@ -1924,25 +1998,33 @@ BEGIN -- Which actions are allowed? IF @CurrentIndexID IS NOT NULL AND EXISTS(SELECT * FROM @ActionsPreferred) BEGIN - IF @CurrentOnReadOnlyFileGroup = 0 AND @CurrentIndexType IN (1,2,3,4,5) AND (@CurrentIsMemoryOptimized = 0 OR @CurrentIsMemoryOptimized IS NULL) AND (@CurrentAllowPageLocks = 1 OR @CurrentIndexType = 5) + IF NOT (@CurrentOnReadOnlyFileGroup = 1) + AND NOT (@CurrentIsMemoryOptimized = 1) + AND NOT (@CurrentAllowPageLocks = 0) BEGIN INSERT INTO @CurrentActionsAllowed ([Action]) VALUES ('INDEX_REORGANIZE') END - IF @CurrentOnReadOnlyFileGroup = 0 AND @CurrentIndexType IN (1,2,3,4,5) AND (@CurrentIsMemoryOptimized = 0 OR @CurrentIsMemoryOptimized IS NULL) + IF NOT (@CurrentOnReadOnlyFileGroup = 1) + AND NOT (@CurrentIsMemoryOptimized = 1) BEGIN INSERT INTO @CurrentActionsAllowed ([Action]) VALUES ('INDEX_REBUILD_OFFLINE') END - IF @CurrentOnReadOnlyFileGroup = 0 - AND (@CurrentIsMemoryOptimized = 0 OR @CurrentIsMemoryOptimized IS NULL) - AND (@CurrentIsPartition = 0 OR @Version >= 12) - AND ((@CurrentIndexType = 1 AND @CurrentIsImageText = 0 AND @CurrentIsNewLOB = 0) - OR (@CurrentIndexType = 2 AND @CurrentIsNewLOB = 0) - OR (@CurrentIndexType = 1 AND @CurrentIsImageText = 0 AND @CurrentIsFileStream = 0 AND @Version >= 11) - OR (@CurrentIndexType = 2 AND @Version >= 11)) - AND (@CurrentIsColumnStore = 0 OR @Version < 11) - AND SERVERPROPERTY('EngineEdition') IN (3,5,8) + IF SERVERPROPERTY('EngineEdition') IN (3, 5, 8) + AND NOT (@CurrentOnReadOnlyFileGroup = 1) + AND NOT (@CurrentIsMemoryOptimized = 1) + AND NOT (@CurrentIsPartition = 1 AND @Version < 12) + AND NOT (@CurrentIndexType = 1 AND @CurrentIsImageText = 1) + AND NOT (@CurrentIndexType = 1 AND @CurrentIsFileStream = 1) + AND NOT (@CurrentIndexType = 1 AND @CurrentIsNewLOB = 1 AND @Version < 11) + AND NOT (@CurrentIndexType = 2 AND @CurrentIsNewLOB = 1 AND @Version < 11) + AND NOT (@CurrentIndexType = 3) + AND NOT (@CurrentIndexType = 4) + AND NOT (@CurrentIndexType = 5 AND @Version < 15) + AND NOT (@CurrentIndexType = 6 AND @Version < 15) + AND NOT (@CurrentIndexType = 1 AND @CurrentHasColumnstore = 1 AND @Version < 13) + AND NOT (@CurrentIndexType = 2 AND @CurrentHasColumnstore = 1 AND @Version < 13) BEGIN INSERT INTO @CurrentActionsAllowed ([Action]) VALUES ('INDEX_REBUILD_ONLINE') @@ -2030,9 +2112,11 @@ BEGIN SET @CurrentComment += 'ImageText: ' + CASE WHEN @CurrentIsImageText = 1 THEN 'Yes' WHEN @CurrentIsImageText = 0 THEN 'No' ELSE 'N/A' END + ', ' SET @CurrentComment += 'NewLOB: ' + CASE WHEN @CurrentIsNewLOB = 1 THEN 'Yes' WHEN @CurrentIsNewLOB = 0 THEN 'No' ELSE 'N/A' END + ', ' SET @CurrentComment += 'FileStream: ' + CASE WHEN @CurrentIsFileStream = 1 THEN 'Yes' WHEN @CurrentIsFileStream = 0 THEN 'No' ELSE 'N/A' END + ', ' - IF @Version >= 11 SET @CurrentComment += 'ColumnStore: ' + CASE WHEN @CurrentIsColumnStore = 1 THEN 'Yes' WHEN @CurrentIsColumnStore = 0 THEN 'No' ELSE 'N/A' END + ', ' + IF @Version >= 11 SET @CurrentComment += 'HasColumnStore: ' + CASE WHEN @CurrentHasColumnstore = 1 THEN 'Yes' WHEN @CurrentHasColumnstore = 0 THEN 'No' ELSE 'N/A' END + ', ' IF @Version >= 14 AND @Resumable = 'Y' SET @CurrentComment += 'Computed: ' + CASE WHEN @CurrentIsComputed = 1 THEN 'Yes' WHEN @CurrentIsComputed = 0 THEN 'No' ELSE 'N/A' END + ', ' + IF @Version >= 14 AND @Resumable = 'Y' AND @CurrentIndexType = 2 SET @CurrentComment += 'ClusteredIndexComputed: ' + CASE WHEN @CurrentIsClusteredIndexComputed = 1 THEN 'Yes' WHEN @CurrentIsClusteredIndexComputed = 0 THEN 'No' ELSE 'N/A' END + ', ' IF @Version >= 14 AND @Resumable = 'Y' SET @CurrentComment += 'Timestamp: ' + CASE WHEN @CurrentIsTimestamp = 1 THEN 'Yes' WHEN @CurrentIsTimestamp = 0 THEN 'No' ELSE 'N/A' END + ', ' + IF @Version >= 14 AND @Resumable = 'Y' SET @CurrentComment += 'HasFilter: ' + CASE WHEN @CurrentHasFilter = 1 THEN 'Yes' WHEN @CurrentHasFilter = 0 THEN 'No' ELSE 'N/A' END + ', ' SET @CurrentComment += 'AllowPageLocks: ' + CASE WHEN @CurrentAllowPageLocks = 1 THEN 'Yes' WHEN @CurrentAllowPageLocks = 0 THEN 'No' ELSE 'N/A' END + ', ' SET @CurrentComment += 'PageCount: ' + ISNULL(CAST(@CurrentPageCount AS nvarchar),'N/A') + ', ' SET @CurrentComment += 'Fragmentation: ' + ISNULL(CAST(@CurrentFragmentationLevel AS nvarchar),'N/A') @@ -2105,10 +2189,10 @@ BEGIN IF (@Version >= 14 OR SERVERPROPERTY('EngineEdition') IN (5,8)) AND @CurrentAction = 'INDEX_REBUILD_ONLINE' AND @CurrentResumableIndexOperation = 0 BEGIN INSERT INTO @CurrentAlterIndexWithClauseArguments (Argument) - SELECT CASE WHEN @Resumable = 'Y' AND @CurrentIndexType IN(1,2) AND @CurrentIsComputed = 0 AND @CurrentIsTimestamp = 0 THEN 'RESUMABLE = ON' ELSE 'RESUMABLE = OFF' END + SELECT CASE WHEN @Resumable = 'Y' AND @CurrentIndexType IN(1,2) AND @CurrentIsComputed = 0 AND @CurrentIsClusteredIndexComputed = 0 AND @CurrentIsTimestamp = 0 AND @CurrentHasFilter = 0 THEN 'RESUMABLE = ON' ELSE 'RESUMABLE = OFF' END END - IF (@Version >= 14 OR SERVERPROPERTY('EngineEdition') IN (5,8)) AND @CurrentAction = 'INDEX_REBUILD_ONLINE' AND @CurrentResumableIndexOperation = 0 AND @Resumable = 'Y' AND @CurrentIndexType IN(1,2) AND @CurrentIsComputed = 0 AND @CurrentIsTimestamp = 0 AND @TimeLimit IS NOT NULL + IF (@Version >= 14 OR SERVERPROPERTY('EngineEdition') IN (5,8)) AND @CurrentAction = 'INDEX_REBUILD_ONLINE' AND @Resumable = 'Y' AND @CurrentIndexType IN(1,2) AND @CurrentIsComputed = 0 AND @CurrentIsClusteredIndexComputed = 0 AND @CurrentIsTimestamp = 0 AND @CurrentHasFilter = 0 AND @TimeLimit IS NOT NULL BEGIN INSERT INTO @CurrentAlterIndexWithClauseArguments (Argument) SELECT 'MAX_DURATION = ' + CAST(DATEDIFF(MINUTE,SYSDATETIME(),DATEADD(SECOND,@TimeLimit,@StartTime)) AS nvarchar(max)) @@ -2220,16 +2304,16 @@ BEGIN SELECT 'SAMPLE ' + CAST(@CurrentStatisticsSample AS nvarchar) + ' PERCENT' END - IF @CurrentStatisticsResample = 'Y' + IF @CurrentNoRecompute = 1 BEGIN INSERT INTO @CurrentUpdateStatisticsWithClauseArguments (Argument) - SELECT 'RESAMPLE' + SELECT 'NORECOMPUTE' END - IF @CurrentNoRecompute = 1 + IF @CurrentStatisticsResample = 'Y' BEGIN INSERT INTO @CurrentUpdateStatisticsWithClauseArguments (Argument) - SELECT 'NORECOMPUTE' + SELECT 'RESAMPLE' END IF EXISTS (SELECT * FROM @CurrentUpdateStatisticsWithClauseArguments) @@ -2310,10 +2394,12 @@ BEGIN SET @CurrentIsImageText = NULL SET @CurrentIsNewLOB = NULL SET @CurrentIsFileStream = NULL - SET @CurrentIsColumnStore = NULL + SET @CurrentHasColumnstore = NULL SET @CurrentIsComputed = NULL + SET @CurrentIsClusteredIndexComputed = NULL SET @CurrentIsTimestamp = NULL SET @CurrentAllowPageLocks = NULL + SET @CurrentHasFilter = NULL SET @CurrentNoRecompute = NULL SET @CurrentIsIncremental = NULL SET @CurrentRowCount = NULL @@ -2412,5 +2498,11 @@ BEGIN END +GO + + ---------------------------------------------------------------------------------------------------- + +END + GO diff --git a/MaintenanceSolution.sql b/MaintenanceSolution.sql index 6228bf7..f257558 100644 --- a/MaintenanceSolution.sql +++ b/MaintenanceSolution.sql @@ -10,7 +10,7 @@ License: https://ola.hallengren.com/license.html GitHub: https://github.com/olahallengren/sql-server-maintenance-solution -Version: 2024-12-27 18:10:28 +Version: 2025-02-19 21:12:35 You can contact me by e-mail at ola@hallengren.com. @@ -23,7 +23,7 @@ https://ola.hallengren.com Modified to add support for Amazon RDS for SQL Server https://github.com/amazon-contributing/aws-sql-server-maintenance-solution -Version: 2024-12-30 12:58 +Version: 2025-03-07 09:14 */ @@ -47,15 +47,15 @@ DECLARE @kms_master_key_arn nvarchar(max) = NULL -- AWS kms master key A DECLARE @ErrorMessage nvarchar(max) -IF IS_SRVROLEMEMBER('sysadmin') = 0 AND NOT (DB_ID('rdsadmin') IS NOT NULL AND SUSER_SNAME(0x01) = 'rdsa') +IF IS_SRVROLEMEMBER('sysadmin') = 0 AND NOT (EXISTS (SELECT * FROM sys.databases WHERE [name] = 'rdsadmin') AND SUSER_SNAME(0x01) = 'rdsa') BEGIN SET @ErrorMessage = 'You need to be a member of the SysAdmin server role to install the SQL Server Maintenance Solution.' RAISERROR(@ErrorMessage,16,1) WITH NOWAIT END -IF NOT (SELECT [compatibility_level] FROM sys.databases WHERE database_id = DB_ID()) >= 90 +IF NOT (SELECT [compatibility_level] FROM sys.databases WHERE [name] = DB_NAME()) >= 90 BEGIN - SET @ErrorMessage = 'The database ' + QUOTENAME(DB_NAME(DB_ID())) + ' has to be in compatibility level 90 or higher.' + SET @ErrorMessage = 'The database ' + QUOTENAME(DB_NAME()) + ' has to be in compatibility level 90 or higher.' RAISERROR(@ErrorMessage,16,1) WITH NOWAIT END @@ -92,7 +92,7 @@ INSERT INTO #Config ([Name], [Value]) VALUES('BackupURL', @BackupURL) INSERT INTO #Config ([Name], [Value]) VALUES('CleanupTime', @CleanupTime) INSERT INTO #Config ([Name], [Value]) VALUES('OutputFileDirectory', @OutputFileDirectory) INSERT INTO #Config ([Name], [Value]) VALUES('LogToTable', @LogToTable) -INSERT INTO #Config ([Name], [Value]) VALUES('DatabaseName', DB_NAME(DB_ID())) +INSERT INTO #Config ([Name], [Value]) VALUES('DatabaseName', DB_NAME()) ---------------------------------------------------------------------------------------------------- --// Original Copyright 2024 Ola Hallengren. Licensed under the MIT License. //-- --// Modifications Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. //-- @@ -242,7 +242,7 @@ BEGIN --// Source: https://ola.hallengren.com //-- --// License: https://ola.hallengren.com/license.html //-- --// GitHub: https://github.com/olahallengren/sql-server-maintenance-solution //-- - --// Version: 2024-12-27 18:10:28 //-- + --// Version: 2025-02-19 21:12:35 //-- --// //-- --// Forked Changes https://github.com/amazon-contributing/aws-sql-server-maintenance-solution //-- --// Version: 2024-12-30 12:58 //-- @@ -305,10 +305,10 @@ BEGIN --// Check core requirements //-- ---------------------------------------------------------------------------------------------------- - IF NOT (SELECT [compatibility_level] FROM sys.databases WHERE database_id = DB_ID()) >= 90 + IF NOT (SELECT [compatibility_level] FROM sys.databases WHERE [name] = DB_NAME()) >= 90 BEGIN INSERT INTO @Errors ([Message], Severity, [State]) - SELECT 'The database ' + QUOTENAME(DB_NAME(DB_ID())) + ' has to be in compatibility level 90 or higher.', 16, 1 + SELECT 'The database ' + QUOTENAME(DB_NAME()) + ' has to be in compatibility level 90 or higher.', 16, 1 END IF NOT (SELECT uses_ansi_nulls FROM sys.sql_modules WHERE [object_id] = @@PROCID) = 1 @@ -553,7 +553,6 @@ BEGIN END GO - SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON @@ -576,7 +575,7 @@ ALTER PROCEDURE [dbo].[DatabaseBackup] @CopyOnly nvarchar(max) = 'N', @ChangeBackupType nvarchar(max) = 'N', @BackupSoftware nvarchar(max) = NULL, -@CheckSum nvarchar(max) = 'N', +@Checksum nvarchar(max) = 'N', @BlockSize int = NULL, @BufferCount int = NULL, @MaxTransferSize int = NULL, @@ -585,6 +584,7 @@ ALTER PROCEDURE [dbo].[DatabaseBackup] @MaxFileSize int = NULL, @CompressionLevel int = NULL, @Description nvarchar(max) = NULL, +@BackupSetName nvarchar(max) = NULL, @Threads int = NULL, @Throttle int = NULL, @Encrypt nvarchar(max) = 'N', @@ -605,6 +605,7 @@ ALTER PROCEDURE [dbo].[DatabaseBackup] @Updateability nvarchar(max) = 'ALL', @AdaptiveCompression nvarchar(max) = NULL, @ModificationLevel int = NULL, +@MinDatabaseSizeForDifferentialBackup int = NULL, @LogSizeSinceLastLogBackup int = NULL, @TimeSinceLastLogBackup int = NULL, @DataDomainBoostHost nvarchar(max) = NULL, @@ -627,6 +628,9 @@ ALTER PROCEDURE [dbo].[DatabaseBackup] @ExcludeLogShippedFromLogBackup nvarchar(max) = 'Y', @DirectoryCheck nvarchar(max) = 'Y', @BackupOptions nvarchar(max) = NULL, +@Stats int = NULL, +@ExpireDate datetime = NULL, +@RetainDays int = NULL, @StringDelimiter nvarchar(max) = ',', @DatabaseOrder nvarchar(max) = NULL, @DatabasesInParallel nvarchar(max) = 'N', @@ -649,7 +653,7 @@ BEGIN --// Source: https://ola.hallengren.com //-- --// License: https://ola.hallengren.com/license.html //-- --// GitHub: https://github.com/olahallengren/sql-server-maintenance-solution //-- - --// Version: 2024-12-27 18:10:28 //-- + --// Version: 2025-02-19 21:12:35 //-- --// //-- --// Modifications Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. //-- ---------------------------------------------------------------------------------------------------- @@ -704,6 +708,7 @@ BEGIN DECLARE @CurrentDifferentialBaseLSN numeric(25,0) DECLARE @CurrentDifferentialBaseIsSnapshot bit DECLARE @CurrentLogLSN numeric(25,0) + DECLARE @BackupInProcess bit DECLARE @CurrentLatestBackup datetime2 DECLARE @CurrentDatabaseNameFS nvarchar(max) DECLARE @CurrentDirectoryStructure nvarchar(max) @@ -711,12 +716,11 @@ BEGIN DECLARE @CurrentMaxFilePathLength nvarchar(max) DECLARE @CurrentFileName nvarchar(max) DECLARE @CurrentDirectoryID int - DECLARE @CurrentDirectoryPath nvarchar(max) + DECLARE @CurrentDirectoryPath nvarchar(4000) DECLARE @CurrentFilePath nvarchar(max) DECLARE @CurrentDate datetime2 DECLARE @CurrentDateUTC datetime2 DECLARE @CurrentCleanupDate datetime2 - DECLARE @CurrentIsDatabaseAccessible bit DECLARE @CurrentReplicaID uniqueidentifier DECLARE @CurrentAvailabilityGroupID uniqueidentifier DECLARE @CurrentAvailabilityGroup nvarchar(max) @@ -847,7 +851,7 @@ BEGIN SET @HostPlatform = 'Windows' END - DECLARE @AmazonRDS bit = CASE WHEN DB_ID('rdsadmin') IS NOT NULL AND SUSER_SNAME(0x01) = 'rdsa' THEN 1 ELSE 0 END + DECLARE @AmazonRDS bit = CASE WHEN EXISTS (SELECT * FROM sys.databases WHERE [name] = 'rdsadmin') AND SUSER_SNAME(0x01) = 'rdsa' THEN 1 ELSE 0 END ---------------------------------------------------------------------------------------------------- --// Log initial information //-- @@ -864,7 +868,7 @@ BEGIN SET @Parameters += ', @CopyOnly = ' + ISNULL('''' + REPLACE(@CopyOnly,'''','''''') + '''','NULL') SET @Parameters += ', @ChangeBackupType = ' + ISNULL('''' + REPLACE(@ChangeBackupType,'''','''''') + '''','NULL') SET @Parameters += ', @BackupSoftware = ' + ISNULL('''' + REPLACE(@BackupSoftware,'''','''''') + '''','NULL') - SET @Parameters += ', @CheckSum = ' + ISNULL('''' + REPLACE(@CheckSum,'''','''''') + '''','NULL') + SET @Parameters += ', @Checksum = ' + ISNULL('''' + REPLACE(@Checksum,'''','''''') + '''','NULL') SET @Parameters += ', @BlockSize = ' + ISNULL(CAST(@BlockSize AS nvarchar),'NULL') SET @Parameters += ', @BufferCount = ' + ISNULL(CAST(@BufferCount AS nvarchar),'NULL') SET @Parameters += ', @MaxTransferSize = ' + ISNULL(CAST(@MaxTransferSize AS nvarchar),'NULL') @@ -873,6 +877,7 @@ BEGIN SET @Parameters += ', @MaxFileSize = ' + ISNULL(CAST(@MaxFileSize AS nvarchar),'NULL') SET @Parameters += ', @CompressionLevel = ' + ISNULL(CAST(@CompressionLevel AS nvarchar),'NULL') SET @Parameters += ', @Description = ' + ISNULL('''' + REPLACE(@Description,'''','''''') + '''','NULL') + SET @Parameters += ', @BackupSetName = ' + ISNULL('''' + REPLACE(@BackupSetName,'''','''''') + '''','NULL') SET @Parameters += ', @Threads = ' + ISNULL(CAST(@Threads AS nvarchar),'NULL') SET @Parameters += ', @Throttle = ' + ISNULL(CAST(@Throttle AS nvarchar),'NULL') SET @Parameters += ', @Encrypt = ' + ISNULL('''' + REPLACE(@Encrypt,'''','''''') + '''','NULL') @@ -893,6 +898,7 @@ BEGIN SET @Parameters += ', @Updateability = ' + ISNULL('''' + REPLACE(@Updateability,'''','''''') + '''','NULL') SET @Parameters += ', @AdaptiveCompression = ' + ISNULL('''' + REPLACE(@AdaptiveCompression,'''','''''') + '''','NULL') SET @Parameters += ', @ModificationLevel = ' + ISNULL(CAST(@ModificationLevel AS nvarchar),'NULL') + SET @Parameters += ', @MinDatabaseSizeForDifferentialBackup = ' + ISNULL('''' + REPLACE(@MinDatabaseSizeForDifferentialBackup,'''','''''') + '''','NULL') SET @Parameters += ', @LogSizeSinceLastLogBackup = ' + ISNULL(CAST(@LogSizeSinceLastLogBackup AS nvarchar),'NULL') SET @Parameters += ', @TimeSinceLastLogBackup = ' + ISNULL(CAST(@TimeSinceLastLogBackup AS nvarchar),'NULL') SET @Parameters += ', @DataDomainBoostHost = ' + ISNULL('''' + REPLACE(@DataDomainBoostHost,'''','''''') + '''','NULL') @@ -914,6 +920,10 @@ BEGIN SET @Parameters += ', @ObjectLevelRecoveryMap = ' + ISNULL('''' + REPLACE(@ObjectLevelRecoveryMap,'''','''''') + '''','NULL') SET @Parameters += ', @ExcludeLogShippedFromLogBackup = ' + ISNULL('''' + REPLACE(@ExcludeLogShippedFromLogBackup,'''','''''') + '''','NULL') SET @Parameters += ', @DirectoryCheck = ' + ISNULL('''' + REPLACE(@DirectoryCheck,'''','''''') + '''','NULL') + SET @Parameters += ', @BackupOptions = ' + ISNULL('''' + REPLACE(@BackupOptions,'''','''''') + '''','NULL') + SET @Parameters += ', @Stats = ' + ISNULL(CAST(@Stats AS nvarchar),'NULL') + SET @Parameters += ', @ExpireDate = ' + ISNULL('''' + CONVERT(nvarchar, @ExpireDate, 21) + '''','NULL') + SET @Parameters += ', @RetainDays = ' + ISNULL(CAST(@RetainDays AS nvarchar),'NULL') SET @Parameters += ', @StringDelimiter = ' + ISNULL('''' + REPLACE(@StringDelimiter,'''','''''') + '''','NULL') SET @Parameters += ', @DatabaseOrder = ' + ISNULL('''' + REPLACE(@DatabaseOrder,'''','''''') + '''','NULL') SET @Parameters += ', @DatabasesInParallel = ' + ISNULL('''' + REPLACE(@DatabasesInParallel,'''','''''') + '''','NULL') @@ -942,7 +952,7 @@ BEGIN SET @StartMessage = 'Platform: ' + @HostPlatform RAISERROR('%s',10,1,@StartMessage) WITH NOWAIT - SET @StartMessage = 'Procedure: ' + QUOTENAME(DB_NAME(DB_ID())) + '.' + QUOTENAME(@SchemaName) + '.' + QUOTENAME(@ObjectName) + SET @StartMessage = 'Procedure: ' + QUOTENAME(DB_NAME()) + '.' + QUOTENAME(@SchemaName) + '.' + QUOTENAME(@ObjectName) RAISERROR('%s',10,1,@StartMessage) WITH NOWAIT SET @StartMessage = 'Parameters: ' + @Parameters @@ -960,10 +970,10 @@ BEGIN --// Check core requirements //-- ---------------------------------------------------------------------------------------------------- - IF NOT (SELECT [compatibility_level] FROM sys.databases WHERE database_id = DB_ID()) >= 90 + IF NOT (SELECT [compatibility_level] FROM sys.databases WHERE [name] = DB_NAME()) >= 90 BEGIN INSERT INTO @Errors ([Message], Severity, [State]) - SELECT 'The database ' + QUOTENAME(DB_NAME(DB_ID())) + ' has to be in compatibility level 90 or higher.', 16, 1 + SELECT 'The database ' + QUOTENAME(DB_NAME()) + ' has to be in compatibility level 90 or higher.', 16, 1 END IF NOT (SELECT uses_ansi_nulls FROM sys.sql_modules WHERE [object_id] = @@PROCID) = 1 @@ -1299,8 +1309,8 @@ BEGIN SET @ErrorMessage = '' SELECT @ErrorMessage = @ErrorMessage + QUOTENAME(DatabaseName) + ', ' FROM @tmpDatabases - WHERE UPPER(DatabaseNameFS) IN(SELECT UPPER(DatabaseNameFS) FROM @tmpDatabases GROUP BY UPPER(DatabaseNameFS) HAVING COUNT(*) > 1) - AND UPPER(DatabaseNameFS) IN(SELECT UPPER(DatabaseNameFS) FROM @tmpDatabases WHERE Selected = 1) + WHERE UPPER(DatabaseNameFS) IN(SELECT UPPER(DatabaseNameFS) FROM @tmpDatabases GROUP BY UPPER(DatabaseNameFS) HAVING COUNT(*) > 1 AND MAX(CAST(Selected AS int)) = 1) + AND DATALENGTH(DatabaseNameFS) > 0 ORDER BY DatabaseName ASC OPTION (RECOMPILE) @@ -1507,7 +1517,7 @@ BEGIN INSERT INTO @Errors ([Message], Severity, [State]) SELECT 'The directory ' + @CurrentRootDirectoryPath + ' does not exist.', 16, 1 END - END + END ---------------------------------------------------------------------------------------------------- UPDATE @Directories @@ -1771,10 +1781,10 @@ BEGIN SELECT 'The value for the parameter @CleanupTime is not supported. Cleanup is not supported if the token {DatabaseName} is not part of the directory.', 16, 5 END - IF @CleanupTime IS NOT NULL AND ((@DirectoryStructure NOT LIKE '%{BackupType}%' OR @DirectoryStructure IS NULL) OR (SERVERPROPERTY('IsHadrEnabled') = 1 AND (@AvailabilityGroupDirectoryStructure NOT LIKE '%{BackupType}%' OR @AvailabilityGroupDirectoryStructure IS NULL))) + IF @CleanupTime IS NOT NULL AND ((@DirectoryStructure NOT LIKE '%{BackupType}%' OR @DirectoryStructure IS NULL) OR (SERVERPROPERTY('IsHadrEnabled') = 1 AND (@AvailabilityGroupDirectoryStructure NOT LIKE '%{BackupType}%' OR @AvailabilityGroupDirectoryStructure IS NULL))) AND (SELECT COUNT(*) FROM (SELECT @FileExtensionFull AS FileExtension UNION SELECT @FileExtensionDiff UNION SELECT @FileExtensionLog) FileExtension) <> 3 BEGIN INSERT INTO @Errors ([Message], Severity, [State]) - SELECT 'The value for the parameter @CleanupTime is not supported. Cleanup is not supported if the token {BackupType} is not part of the directory.', 16, 6 + SELECT 'The value for the parameter @CleanupTime is not supported. Cleanup is not supported if the token {BackupType} is not part of the directory and the file extensions are not unique.', 16, 6 END IF @CleanupTime IS NOT NULL AND @CopyOnly = 'Y' AND ((@DirectoryStructure NOT LIKE '%{CopyOnly}%' OR @DirectoryStructure IS NULL) OR (SERVERPROPERTY('IsHadrEnabled') = 1 AND (@AvailabilityGroupDirectoryStructure NOT LIKE '%{CopyOnly}%' OR @AvailabilityGroupDirectoryStructure IS NULL))) @@ -1899,10 +1909,10 @@ BEGIN ---------------------------------------------------------------------------------------------------- - IF @CheckSum NOT IN ('Y','N') OR @CheckSum IS NULL + IF @Checksum NOT IN ('Y','N') OR @Checksum IS NULL BEGIN INSERT INTO @Errors ([Message], Severity, [State]) - SELECT 'The value for the parameter @CheckSum is not supported.', 16, 1 + SELECT 'The value for the parameter @Checksum is not supported.', 16, 1 END ---------------------------------------------------------------------------------------------------- @@ -2167,6 +2177,13 @@ BEGIN ---------------------------------------------------------------------------------------------------- + IF LEN(@BackupSetName) > 128 + BEGIN + INSERT INTO @Errors ([Message], Severity, [State]) + SELECT 'The value for the parameter @BackupSetName is not supported.', 16, 1 + END + + ---------------------------------------------------------------------------------------------------- IF @Threads IS NOT NULL AND (@BackupSoftware NOT IN('LITESPEED','SQLBACKUP','SQLSAFE') OR @BackupSoftware IS NULL) BEGIN INSERT INTO @Errors ([Message], Severity, [State]) @@ -2514,16 +2531,35 @@ BEGIN SELECT 'The value for the parameter @ModificationLevel is not supported.', 16, 1 END + IF @ModificationLevel <= 0 OR @ModificationLevel > 100 + BEGIN + INSERT INTO @Errors ([Message], Severity, [State]) + SELECT 'The value for the parameter @ModificationLevel is not supported.', 16, 2 + END IF @ModificationLevel IS NOT NULL AND @ChangeBackupType = 'N' BEGIN INSERT INTO @Errors ([Message], Severity, [State]) - SELECT 'The parameter @ModificationLevel can only be used together with @ChangeBackupType = ''Y''.', 16, 2 + SELECT 'The parameter @ModificationLevel can only be used together with @ChangeBackupType = ''Y''.', 16, 3 END IF @ModificationLevel IS NOT NULL AND @BackupType <> 'DIFF' BEGIN INSERT INTO @Errors ([Message], Severity, [State]) - SELECT 'The parameter @ModificationLevel can only be used for differential backups.', 16, 3 + SELECT 'The parameter @ModificationLevel can only be used for differential backups.', 16, 4 + END + + ---------------------------------------------------------------------------------------------------- + + IF @MinDatabaseSizeForDifferentialBackup <= 0 + BEGIN + INSERT INTO @Errors ([Message], Severity, [State]) + SELECT 'The value for the parameter @MinDatabaseSizeForDifferentialBackup is not supported.', 16, 1 + END + + IF @MinDatabaseSizeForDifferentialBackup IS NOT NULL AND @BackupType <> 'DIFF' + BEGIN + INSERT INTO @Errors ([Message], Severity, [State]) + SELECT 'The parameter @MinDatabaseSizeForDifferentialBackup can only be used for differential backups.', 16, 2 END ---------------------------------------------------------------------------------------------------- @@ -2728,7 +2764,7 @@ BEGIN ---------------------------------------------------------------------------------------------------- - IF EXISTS (SELECT * FROM (SELECT REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@DirectoryStructure,'{DirectorySeparator}',''),'{ServerName}',''),'{InstanceName}',''),'{ServiceName}',''),'{ClusterName}',''),'{AvailabilityGroupName}',''),'{DatabaseName}',''),'{BackupType}',''),'{Partial}',''),'{CopyOnly}',''),'{Description}',''),'{Year}',''),'{Month}',''),'{Day}',''),'{Week}',''),'{Hour}',''),'{Minute}',''),'{Second}',''),'{Millisecond}',''),'{Microsecond}',''),'{MajorVersion}',''),'{MinorVersion}','') AS DirectoryStructure) Temp WHERE DirectoryStructure LIKE '%{%' OR DirectoryStructure LIKE '%}%') + IF EXISTS (SELECT * FROM (SELECT REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@DirectoryStructure,'{DirectorySeparator}',''),'{ServerName}',''),'{InstanceName}',''),'{ServiceName}',''),'{ClusterName}',''),'{AvailabilityGroupName}',''),'{DatabaseName}',''),'{BackupType}',''),'{Partial}',''),'{CopyOnly}',''),'{Description}',''),'{BackupSetName}',''),'{Year}',''),'{Month}',''),'{Day}',''),'{Week}',''),'{Weekday}',''),'{Hour}',''),'{Minute}',''),'{Second}',''),'{Millisecond}',''),'{Microsecond}',''),'{MajorVersion}',''),'{MinorVersion}','') AS DirectoryStructure) Temp WHERE DirectoryStructure LIKE '%{%' OR DirectoryStructure LIKE '%}%') BEGIN INSERT INTO @Errors ([Message], Severity, [State]) SELECT 'The parameter @DirectoryStructure contains one or more tokens that are not supported.', 16, 1 @@ -2736,7 +2772,7 @@ BEGIN ---------------------------------------------------------------------------------------------------- - IF EXISTS (SELECT * FROM (SELECT REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@AvailabilityGroupDirectoryStructure,'{DirectorySeparator}',''),'{ServerName}',''),'{InstanceName}',''),'{ServiceName}',''),'{ClusterName}',''),'{AvailabilityGroupName}',''),'{DatabaseName}',''),'{BackupType}',''),'{Partial}',''),'{CopyOnly}',''),'{Description}',''),'{Year}',''),'{Month}',''),'{Day}',''),'{Week}',''),'{Hour}',''),'{Minute}',''),'{Second}',''),'{Millisecond}',''),'{Microsecond}',''),'{MajorVersion}',''),'{MinorVersion}','') AS AvailabilityGroupDirectoryStructure) Temp WHERE AvailabilityGroupDirectoryStructure LIKE '%{%' OR AvailabilityGroupDirectoryStructure LIKE '%}%') + IF EXISTS (SELECT * FROM (SELECT REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@AvailabilityGroupDirectoryStructure,'{DirectorySeparator}',''),'{ServerName}',''),'{InstanceName}',''),'{ServiceName}',''),'{ClusterName}',''),'{AvailabilityGroupName}',''),'{DatabaseName}',''),'{BackupType}',''),'{Partial}',''),'{CopyOnly}',''),'{Description}',''),'{BackupSetName}',''),'{Year}',''),'{Month}',''),'{Day}',''),'{Week}',''),'{Weekday}',''),'{Hour}',''),'{Minute}',''),'{Second}',''),'{Millisecond}',''),'{Microsecond}',''),'{MajorVersion}',''),'{MinorVersion}','') AS AvailabilityGroupDirectoryStructure) Temp WHERE AvailabilityGroupDirectoryStructure LIKE '%{%' OR AvailabilityGroupDirectoryStructure LIKE '%}%') BEGIN INSERT INTO @Errors ([Message], Severity, [State]) SELECT 'The parameter @AvailabilityGroupDirectoryStructure contains one or more tokens that are not supported.', 16, 1 @@ -2744,7 +2780,7 @@ BEGIN ---------------------------------------------------------------------------------------------------- - IF EXISTS (SELECT * FROM (SELECT REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@FileName,'{DirectorySeparator}',''),'{ServerName}',''),'{InstanceName}',''),'{ServiceName}',''),'{ClusterName}',''),'{AvailabilityGroupName}',''),'{DatabaseName}',''),'{BackupType}',''),'{Partial}',''),'{CopyOnly}',''),'{Description}',''),'{Year}',''),'{Month}',''),'{Day}',''),'{Week}',''),'{Hour}',''),'{Minute}',''),'{Second}',''),'{Millisecond}',''),'{Microsecond}',''),'{FileNumber}',''),'{NumberOfFiles}',''),'{FileExtension}',''),'{MajorVersion}',''),'{MinorVersion}','') AS [FileName]) Temp WHERE [FileName] LIKE '%{%' OR [FileName] LIKE '%}%') + IF EXISTS (SELECT * FROM (SELECT REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@FileName,'{DirectorySeparator}',''),'{ServerName}',''),'{InstanceName}',''),'{ServiceName}',''),'{ClusterName}',''),'{AvailabilityGroupName}',''),'{DatabaseName}',''),'{BackupType}',''),'{Partial}',''),'{CopyOnly}',''),'{Description}',''),'{BackupSetName}',''),'{Year}',''),'{Month}',''),'{Day}',''),'{Week}',''),'{Weekday}',''),'{Hour}',''),'{Minute}',''),'{Second}',''),'{Millisecond}',''),'{Microsecond}',''),'{FileNumber}',''),'{NumberOfFiles}',''),'{FileExtension}',''),'{MajorVersion}',''),'{MinorVersion}','') AS [FileName]) Temp WHERE [FileName] LIKE '%{%' OR [FileName] LIKE '%}%') BEGIN INSERT INTO @Errors ([Message], Severity, [State]) SELECT 'The parameter @FileName contains one or more tokens that are not supported.', 16, 1 @@ -2752,7 +2788,7 @@ BEGIN ---------------------------------------------------------------------------------------------------- - IF EXISTS (SELECT * FROM (SELECT REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@AvailabilityGroupFileName,'{DirectorySeparator}',''),'{ServerName}',''),'{InstanceName}',''),'{ServiceName}',''),'{ClusterName}',''),'{AvailabilityGroupName}',''),'{DatabaseName}',''),'{BackupType}',''),'{Partial}',''),'{CopyOnly}',''),'{Description}',''),'{Year}',''),'{Month}',''),'{Day}',''),'{Week}',''),'{Hour}',''),'{Minute}',''),'{Second}',''),'{Millisecond}',''),'{Microsecond}',''),'{FileNumber}',''),'{NumberOfFiles}',''),'{FileExtension}',''),'{MajorVersion}',''),'{MinorVersion}','') AS AvailabilityGroupFileName) Temp WHERE AvailabilityGroupFileName LIKE '%{%' OR AvailabilityGroupFileName LIKE '%}%') + IF EXISTS (SELECT * FROM (SELECT REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@AvailabilityGroupFileName,'{DirectorySeparator}',''),'{ServerName}',''),'{InstanceName}',''),'{ServiceName}',''),'{ClusterName}',''),'{AvailabilityGroupName}',''),'{DatabaseName}',''),'{BackupType}',''),'{Partial}',''),'{CopyOnly}',''),'{Description}',''),'{BackupSetName}',''),'{Year}',''),'{Month}',''),'{Day}',''),'{Week}',''),'{Weekday}',''),'{Hour}',''),'{Minute}',''),'{Second}',''),'{Millisecond}',''),'{Microsecond}',''),'{FileNumber}',''),'{NumberOfFiles}',''),'{FileExtension}',''),'{MajorVersion}',''),'{MinorVersion}','') AS AvailabilityGroupFileName) Temp WHERE AvailabilityGroupFileName LIKE '%{%' OR AvailabilityGroupFileName LIKE '%}%') BEGIN INSERT INTO @Errors ([Message], Severity, [State]) SELECT 'The parameter @AvailabilityGroupFileName contains one or more tokens that are not supported.', 16, 1 @@ -2874,6 +2910,43 @@ BEGIN ---------------------------------------------------------------------------------------------------- + IF @BackupOptions IS NOT NULL AND @URL IS NULL + BEGIN + INSERT INTO @Errors ([Message], Severity, [State]) + SELECT 'The value for the parameter @BackupOptions is not supported.', 16, 1 + END + + ---------------------------------------------------------------------------------------------------- + + IF @Stats <= 0 OR @Stats > 100 + BEGIN + INSERT INTO @Errors ([Message], Severity, [State]) + SELECT 'The value for the parameter @Stats is not supported.', 16, 1 + END + + ---------------------------------------------------------------------------------------------------- + + IF @ExpireDate IS NOT NULL AND @BackupSoftware <> 'LITESPEED' + BEGIN + INSERT INTO @Errors ([Message], Severity, [State]) + SELECT 'The value for the parameter @ExpireDate is not supported.', 16, 1 + END + + ---------------------------------------------------------------------------------------------------- + + IF @RetainDays < 0 + BEGIN + INSERT INTO @Errors ([Message], Severity, [State]) + SELECT 'The value for the parameter @RetainDays is not supported.', 16, 1 + END + + IF @RetainDays IS NOT NULL AND @BackupSoftware <> 'LITESPEED' + BEGIN + INSERT INTO @Errors ([Message], Severity, [State]) + SELECT 'The value for the parameter @RetainDays is not supported.', 16, 1 + END + + ---------------------------------------------------------------------------------------------------- IF @StringDelimiter IS NULL OR LEN(@StringDelimiter) > 1 BEGIN INSERT INTO @Errors ([Message], Severity, [State]) @@ -3307,18 +3380,6 @@ BEGIN WHEN @MaxTransferSize IS NULL AND @Compress = 'Y' AND @CurrentIsEncrypted = 1 AND @BackupSoftware IS NULL AND (@Version >= 13 AND @Version < 15.0404316) AND @Credential IS NULL THEN 65537 END - IF @CurrentDatabaseState = 'ONLINE' AND NOT (@CurrentInStandby = 1) - BEGIN - IF EXISTS (SELECT * FROM sys.database_recovery_status WHERE database_id = DB_ID(@CurrentDatabaseName) AND database_guid IS NOT NULL) - BEGIN - SET @CurrentIsDatabaseAccessible = 1 - END - ELSE - BEGIN - SET @CurrentIsDatabaseAccessible = 0 - END - END - IF @Version >= 11 AND SERVERPROPERTY('IsHadrEnabled') = 1 BEGIN SELECT @CurrentReplicaID = databases.replica_id @@ -3362,22 +3423,23 @@ BEGIN AND EXISTS(SELECT * FROM sys.all_columns WHERE object_id = OBJECT_ID('sys.dm_db_file_space_usage') AND name = 'modified_extent_page_count') AND (@CurrentAvailabilityGroupRole = 'PRIMARY' OR @CurrentAvailabilityGroupRole IS NULL) AND (@BackupType IN('DIFF','FULL') OR (@ChangeBackupType = 'Y' AND @CurrentBackupType = 'LOG' AND @CurrentRecoveryModel IN('FULL','BULK_LOGGED') AND @CurrentLogLSN IS NULL AND @CurrentDatabaseName <> 'master')) - AND (@ModificationLevel IS NOT NULL OR @MinBackupSizeForMultipleFiles IS NOT NULL OR @MaxFileSize IS NOT NULL) + AND (@ModificationLevel IS NOT NULL OR @MinBackupSizeForMultipleFiles IS NOT NULL OR @MaxFileSize IS NOT NULL OR @MinDatabaseSizeForDifferentialBackup IS NOT NULL) BEGIN SET @CurrentCommand = 'SELECT @ParamAllocatedExtentPageCount = SUM(allocated_extent_page_count), @ParamModifiedExtentPageCount = SUM(modified_extent_page_count) FROM sys.dm_db_file_space_usage' EXECUTE @CurrentDatabase_sp_executesql @stmt = @CurrentCommand, @params = N'@ParamAllocatedExtentPageCount bigint OUTPUT, @ParamModifiedExtentPageCount bigint OUTPUT', @ParamAllocatedExtentPageCount = @CurrentAllocatedExtentPageCount OUTPUT, @ParamModifiedExtentPageCount = @CurrentModifiedExtentPageCount OUTPUT END + SET @BackupInProcess = CASE WHEN EXISTS(SELECT * FROM sys.dm_exec_requests WHERE database_id = DB_ID(@CurrentDatabaseName) AND command = 'BACKUP DATABASE') THEN 1 ELSE 0 END SET @CurrentBackupType = @BackupType IF @ChangeBackupType = 'Y' BEGIN - IF @CurrentBackupType = 'LOG' AND @CurrentRecoveryModel IN('FULL','BULK_LOGGED') AND @CurrentLogLSN IS NULL AND @CurrentDatabaseName <> 'master' + IF @CurrentBackupType = 'LOG' AND @CurrentRecoveryModel IN('FULL','BULK_LOGGED') AND @CurrentLogLSN IS NULL AND @CurrentDatabaseName <> 'master' AND @BackupInProcess = 0 BEGIN SET @CurrentBackupType = 'DIFF' END - IF @CurrentBackupType = 'DIFF' AND (@CurrentDatabaseName = 'master' OR @CurrentDifferentialBaseLSN IS NULL OR (@CurrentModifiedExtentPageCount * 1. / @CurrentAllocatedExtentPageCount * 100 >= @ModificationLevel)) + IF @CurrentBackupType = 'DIFF' AND (@CurrentDatabaseName = 'master' OR @CurrentDifferentialBaseLSN IS NULL OR (@CurrentModifiedExtentPageCount * 1. / @CurrentAllocatedExtentPageCount * 100 >= @ModificationLevel) OR (COALESCE(CAST(@CurrentAllocatedExtentPageCount AS bigint) * 8192, CAST(@CurrentDatabaseSize AS bigint) * 8192) < CAST(@MinDatabaseSizeForDifferentialBackup AS bigint) * 1024 * 1024)) BEGIN SET @CurrentBackupType = 'FULL' END @@ -3434,8 +3496,9 @@ BEGIN FROM CurrentDatabase SELECT @CurrentDatabaseMirroringRole = UPPER(mirroring_role_desc) - FROM sys.database_mirroring - WHERE database_id = DB_ID(@CurrentDatabaseName) + FROM sys.database_mirroring database_mirroring + INNER JOIN sys.databases databases ON database_mirroring.database_id = databases.database_id + WHERE databases.[name] = @CurrentDatabaseName ---------------------------------------------------------------------------------------------------- --// Original Copyright 2024 Ola Hallengren. Licensed under the MIT License. //-- @@ -3454,11 +3517,11 @@ BEGIN END ---------------------------------------------------------------------------------------------------- - IF @CurrentIsDatabaseAccessible IS NOT NULL - BEGIN - SET @DatabaseMessage = 'Is accessible: ' + CASE WHEN @CurrentIsDatabaseAccessible = 1 THEN 'Yes' ELSE 'No' END - RAISERROR('%s',10,1,@DatabaseMessage) WITH NOWAIT - END + + + + + IF @CurrentAvailabilityGroup IS NOT NULL BEGIN @@ -3499,6 +3562,11 @@ BEGIN SET @DatabaseMessage = 'Last log backup LSN: ' + ISNULL(CAST(@CurrentLogLSN AS nvarchar),'N/A') RAISERROR('%s',10,1,@DatabaseMessage) WITH NOWAIT + IF @CurrentBackupType = 'LOG' AND @BackupInProcess = 1 + BEGIN + SET @DatabaseMessage = 'Full or differential backup in process: ' + CASE WHEN @BackupInProcess = 1 THEN 'Yes' WHEN @BackupInProcess = 0 THEN 'No' ELSE 'N/A' END + RAISERROR('%s',10,1,@DatabaseMessage) WITH NOWAIT + END IF @CurrentBackupType IN('DIFF','FULL') AND EXISTS(SELECT * FROM sys.all_columns WHERE object_id = OBJECT_ID('sys.dm_db_file_space_usage') AND name = 'modified_extent_page_count') BEGIN SET @DatabaseMessage = 'Allocated extent page count: ' + ISNULL(CAST(@CurrentAllocatedExtentPageCount AS nvarchar) + ' (' + CAST(@CurrentAllocatedExtentPageCount * 1. * 8 / 1024 AS nvarchar) + ' MB)','N/A') @@ -3520,7 +3588,7 @@ BEGIN RAISERROR(@EmptyLine,10,1) WITH NOWAIT IF @CurrentDatabaseState = 'ONLINE' - AND NOT (@CurrentUserAccess = 'SINGLE_USER' AND @CurrentIsDatabaseAccessible = 0) + AND NOT (@CurrentUserAccess = 'SINGLE_USER') AND NOT (@CurrentInStandby = 1) AND NOT (@CurrentBackupType = 'LOG' AND @CurrentRecoveryModel = 'SIMPLE') AND NOT (@CurrentBackupType = 'LOG' AND @CurrentRecoveryModel IN('FULL','BULK_LOGGED') AND @CurrentLogLSN IS NULL) @@ -3536,6 +3604,7 @@ BEGIN AND NOT (@CurrentIsReadOnly = 0 AND @Updateability = 'READ_ONLY') AND NOT (@CurrentBackupType = 'LOG' AND @LogSizeSinceLastLogBackup IS NOT NULL AND @TimeSinceLastLogBackup IS NOT NULL AND NOT(@CurrentLogSizeSinceLastLogBackup >= @LogSizeSinceLastLogBackup OR @CurrentLogSizeSinceLastLogBackup IS NULL OR DATEDIFF(SECOND,@CurrentLastLogBackup,SYSDATETIME()) >= @TimeSinceLastLogBackup OR @CurrentLastLogBackup IS NULL)) AND NOT (@CurrentBackupType = 'LOG' AND @Updateability = 'READ_ONLY' AND @BackupSoftware = 'DATA_DOMAIN_BOOST') + AND NOT (@CurrentBackupType = 'DIFF' AND @MinDatabaseSizeForDifferentialBackup IS NOT NULL AND (COALESCE(CAST(@CurrentAllocatedExtentPageCount AS bigint) * 8192, CAST(@CurrentDatabaseSize AS bigint) * 8192) < CAST(@MinDatabaseSizeForDifferentialBackup AS bigint) * 1024 * 1024)) BEGIN IF @CurrentBackupType = 'LOG' AND (@CleanupTime IS NOT NULL OR @MirrorCleanupTime IS NOT NULL) @@ -3575,6 +3644,7 @@ BEGIN IF SERVERPROPERTY('InstanceName') IS NULL SET @CurrentDirectoryStructure = REPLACE(@CurrentDirectoryStructure,'{InstanceName}','') IF @@SERVICENAME IS NULL SET @CurrentDirectoryStructure = REPLACE(@CurrentDirectoryStructure,'{ServiceName}','') IF @Description IS NULL SET @CurrentDirectoryStructure = REPLACE(@CurrentDirectoryStructure,'{Description}','') + IF @BackupSetName IS NULL SET @CurrentDirectoryStructure = REPLACE(@CurrentDirectoryStructure,'{BackupSetName}','') IF @Directory IS NULL AND @MirrorDirectory IS NULL AND @URL IS NULL AND @DefaultDirectory LIKE '%' + '.' + @@SERVICENAME + @DirectorySeparator + 'MSSQL' + @DirectorySeparator + 'Backup' BEGIN @@ -3732,10 +3802,12 @@ BEGIN SET @CurrentDirectoryStructure = REPLACE(@CurrentDirectoryStructure,'{Partial}','PARTIAL') SET @CurrentDirectoryStructure = REPLACE(@CurrentDirectoryStructure,'{CopyOnly}','COPY_ONLY') SET @CurrentDirectoryStructure = REPLACE(@CurrentDirectoryStructure,'{Description}',LTRIM(RTRIM(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(ISNULL(@Description,''),'\',''),'/',''),':',''),'*',''),'?',''),'"',''),'<',''),'>',''),'|','')))) + SET @CurrentDirectoryStructure = REPLACE(@CurrentDirectoryStructure,'{BackupSetName}',LTRIM(RTRIM(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(ISNULL(@BackupSetName,''),'\',''),'/',''),':',''),'*',''),'?',''),'"',''),'<',''),'>',''),'|','')))) SET @CurrentDirectoryStructure = REPLACE(@CurrentDirectoryStructure,'{Year}',CAST(DATEPART(YEAR,CASE WHEN @TokenTimezone = 'UTC' THEN @CurrentDateUTC ELSE @CurrentDate END) AS nvarchar)) SET @CurrentDirectoryStructure = REPLACE(@CurrentDirectoryStructure,'{Month}',RIGHT('0' + CAST(DATEPART(MONTH,CASE WHEN @TokenTimezone = 'UTC' THEN @CurrentDateUTC ELSE @CurrentDate END) AS nvarchar),2)) SET @CurrentDirectoryStructure = REPLACE(@CurrentDirectoryStructure,'{Day}',RIGHT('0' + CAST(DATEPART(DAY,CASE WHEN @TokenTimezone = 'UTC' THEN @CurrentDateUTC ELSE @CurrentDate END) AS nvarchar),2)) SET @CurrentDirectoryStructure = REPLACE(@CurrentDirectoryStructure,'{Week}',RIGHT('0' + CAST(DATEPART(WEEK,CASE WHEN @TokenTimezone = 'UTC' THEN @CurrentDateUTC ELSE @CurrentDate END) AS nvarchar),2)) + SET @CurrentDirectoryStructure = REPLACE(@CurrentDirectoryStructure,'{Weekday}',DATENAME(WEEKDAY,CASE WHEN @TokenTimezone = 'UTC' THEN @CurrentDateUTC ELSE @CurrentDate END)) SET @CurrentDirectoryStructure = REPLACE(@CurrentDirectoryStructure,'{Hour}',RIGHT('0' + CAST(DATEPART(HOUR,CASE WHEN @TokenTimezone = 'UTC' THEN @CurrentDateUTC ELSE @CurrentDate END) AS nvarchar),2)) SET @CurrentDirectoryStructure = REPLACE(@CurrentDirectoryStructure,'{Minute}',RIGHT('0' + CAST(DATEPART(MINUTE,CASE WHEN @TokenTimezone = 'UTC' THEN @CurrentDateUTC ELSE @CurrentDate END) AS nvarchar),2)) SET @CurrentDirectoryStructure = REPLACE(@CurrentDirectoryStructure,'{Second}',RIGHT('0' + CAST(DATEPART(SECOND,CASE WHEN @TokenTimezone = 'UTC' THEN @CurrentDateUTC ELSE @CurrentDate END) AS nvarchar),2)) @@ -3782,6 +3854,7 @@ BEGIN IF SERVERPROPERTY('InstanceName') IS NULL SET @CurrentDatabaseFileName = REPLACE(@CurrentDatabaseFileName,'{InstanceName}','') IF @@SERVICENAME IS NULL SET @CurrentDatabaseFileName = REPLACE(@CurrentDatabaseFileName,'{ServiceName}','') IF @Description IS NULL SET @CurrentDatabaseFileName = REPLACE(@CurrentDatabaseFileName,'{Description}','') + IF @BackupSetName IS NULL SET @CurrentDatabaseFileName = REPLACE(@CurrentDatabaseFileName,'{BackupSetName}','') IF @CurrentNumberOfFiles = 1 SET @CurrentDatabaseFileName = REPLACE(@CurrentDatabaseFileName,'{FileNumber}','') IF @CurrentNumberOfFiles = 1 SET @CurrentDatabaseFileName = REPLACE(@CurrentDatabaseFileName,'{NumberOfFiles}','') @@ -3893,10 +3966,12 @@ BEGIN SET @CurrentDatabaseFileName = REPLACE(@CurrentDatabaseFileName,'{Partial}','PARTIAL') SET @CurrentDatabaseFileName = REPLACE(@CurrentDatabaseFileName,'{CopyOnly}','COPY_ONLY') SET @CurrentDatabaseFileName = REPLACE(@CurrentDatabaseFileName,'{Description}',LTRIM(RTRIM(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(ISNULL(@Description,''),'\',''),'/',''),':',''),'*',''),'?',''),'"',''),'<',''),'>',''),'|','')))) + SET @CurrentDatabaseFileName = REPLACE(@CurrentDatabaseFileName,'{BackupSetName}',LTRIM(RTRIM(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(ISNULL(@BackupSetName,''),'\',''),'/',''),':',''),'*',''),'?',''),'"',''),'<',''),'>',''),'|','')))) SET @CurrentDatabaseFileName = REPLACE(@CurrentDatabaseFileName,'{Year}',CAST(DATEPART(YEAR,CASE WHEN @TokenTimezone = 'UTC' THEN @CurrentDateUTC ELSE @CurrentDate END) AS nvarchar)) SET @CurrentDatabaseFileName = REPLACE(@CurrentDatabaseFileName,'{Month}',RIGHT('0' + CAST(DATEPART(MONTH,CASE WHEN @TokenTimezone = 'UTC' THEN @CurrentDateUTC ELSE @CurrentDate END) AS nvarchar),2)) SET @CurrentDatabaseFileName = REPLACE(@CurrentDatabaseFileName,'{Day}',RIGHT('0' + CAST(DATEPART(DAY,CASE WHEN @TokenTimezone = 'UTC' THEN @CurrentDateUTC ELSE @CurrentDate END) AS nvarchar),2)) SET @CurrentDatabaseFileName = REPLACE(@CurrentDatabaseFileName,'{Week}',RIGHT('0' + CAST(DATEPART(WEEK,CASE WHEN @TokenTimezone = 'UTC' THEN @CurrentDateUTC ELSE @CurrentDate END) AS nvarchar),2)) + SET @CurrentDatabaseFileName = REPLACE(@CurrentDatabaseFileName,'{Weekday}',DATENAME(WEEKDAY,CASE WHEN @TokenTimezone = 'UTC' THEN @CurrentDateUTC ELSE @CurrentDate END)) SET @CurrentDatabaseFileName = REPLACE(@CurrentDatabaseFileName,'{Hour}',RIGHT('0' + CAST(DATEPART(HOUR,CASE WHEN @TokenTimezone = 'UTC' THEN @CurrentDateUTC ELSE @CurrentDate END) AS nvarchar),2)) SET @CurrentDatabaseFileName = REPLACE(@CurrentDatabaseFileName,'{Minute}',RIGHT('0' + CAST(DATEPART(MINUTE,CASE WHEN @TokenTimezone = 'UTC' THEN @CurrentDateUTC ELSE @CurrentDate END) AS nvarchar),2)) SET @CurrentDatabaseFileName = REPLACE(@CurrentDatabaseFileName,'{Second}',RIGHT('0' + CAST(DATEPART(SECOND,CASE WHEN @TokenTimezone = 'UTC' THEN @CurrentDateUTC ELSE @CurrentDate END) AS nvarchar),2)) @@ -4081,21 +4156,37 @@ BEGIN BREAK END - SET @CurrentDatabaseContext = 'master' + IF @DirectoryCheck = 'Y' + BEGIN + INSERT INTO @DirectoryInfo (FileExists, FileIsADirectory, ParentDirectoryExists) + EXECUTE [master].dbo.xp_fileexist @CurrentDirectoryPath + END - SET @CurrentCommandType = 'xp_create_subdir' + IF NOT EXISTS (SELECT * FROM @DirectoryInfo WHERE FileExists = 0 AND FileIsADirectory = 1 AND ParentDirectoryExists = 1) + BEGIN + SET @CurrentDatabaseContext = 'master' - SET @CurrentCommand = 'DECLARE @ReturnCode int EXECUTE @ReturnCode = dbo.xp_create_subdir N''' + REPLACE(@CurrentDirectoryPath,'''','''''') + ''' IF @ReturnCode <> 0 RAISERROR(''Error creating directory.'', 16, 1)' + SET @CurrentCommandType = 'xp_create_subdir' - EXECUTE @CurrentCommandOutput = dbo.CommandExecute @DatabaseContext = @CurrentDatabaseContext, @Command = @CurrentCommand, @CommandType = @CurrentCommandType, @Mode = 1, @DatabaseName = @CurrentDatabaseName, @LogToTable = @LogToTable, @Execute = @Execute - SET @Error = @@ERROR - IF @Error <> 0 SET @CurrentCommandOutput = @Error - IF @CurrentCommandOutput <> 0 SET @ReturnCode = @CurrentCommandOutput + SET @CurrentCommand = 'DECLARE @ReturnCode int EXECUTE @ReturnCode = dbo.xp_create_subdir N''' + REPLACE(@CurrentDirectoryPath,'''','''''') + ''' IF @ReturnCode <> 0 RAISERROR(''Error creating directory.'', 16, 1)' - UPDATE @CurrentDirectories - SET CreateCompleted = 1, - CreateOutput = @CurrentCommandOutput - WHERE ID = @CurrentDirectoryID + EXECUTE @CurrentCommandOutput = dbo.CommandExecute @DatabaseContext = @CurrentDatabaseContext, @Command = @CurrentCommand, @CommandType = @CurrentCommandType, @Mode = 1, @DatabaseName = @CurrentDatabaseName, @LogToTable = @LogToTable, @Execute = @Execute + SET @Error = @@ERROR + IF @Error <> 0 SET @CurrentCommandOutput = @Error + IF @CurrentCommandOutput <> 0 SET @ReturnCode = @CurrentCommandOutput + + UPDATE @CurrentDirectories + SET CreateCompleted = 1, + CreateOutput = @CurrentCommandOutput + WHERE ID = @CurrentDirectoryID + END + ELSE + BEGIN + UPDATE @CurrentDirectories + SET CreateCompleted = 1, + CreateOutput = 0 + WHERE ID = @CurrentDirectoryID + END SET @CurrentDirectoryID = NULL SET @CurrentDirectoryPath = NULL @@ -4104,6 +4195,8 @@ BEGIN SET @CurrentCommand = NULL SET @CurrentCommandOutput = NULL SET @CurrentCommandType = NULL + + DELETE FROM @DirectoryInfo END END @@ -4266,64 +4359,68 @@ BEGIN SELECT @CurrentCommand = CASE WHEN @CurrentBackupType IN('DIFF','FULL') THEN 'BACKUP DATABASE ' + QUOTENAME(@CurrentDatabaseName) WHEN @CurrentBackupType = 'LOG' THEN 'BACKUP LOG ' + QUOTENAME(@CurrentDatabaseName) - END - - IF @ReadWriteFileGroups = 'Y' AND @CurrentDatabaseName <> 'master' SET @CurrentCommand += ' READ_WRITE_FILEGROUPS' + END - SET @CurrentCommand += ' TO' + IF @ReadWriteFileGroups = 'Y' AND @CurrentDatabaseName <> 'master' SET @CurrentCommand += ' READ_WRITE_FILEGROUPS' - SELECT @CurrentCommand += ' ' + [Type] + ' = N''' + REPLACE(FilePath,'''','''''') + '''' + CASE WHEN ROW_NUMBER() OVER (ORDER BY FilePath ASC) <> @CurrentNumberOfFiles THEN ',' ELSE '' END - FROM @CurrentFiles - WHERE Mirror = 0 - ORDER BY FilePath ASC - - IF EXISTS(SELECT * FROM @CurrentFiles WHERE Mirror = 1) - BEGIN - SET @CurrentCommand += ' MIRROR TO' - - SELECT @CurrentCommand += ' ' + [Type] + ' = N''' + REPLACE(FilePath,'''','''''') + '''' + CASE WHEN ROW_NUMBER() OVER (ORDER BY FilePath ASC) <> @CurrentNumberOfFiles THEN ',' ELSE '' END - FROM @CurrentFiles - WHERE Mirror = 1 - ORDER BY FilePath ASC - END - - SET @CurrentCommand += ' WITH ' - IF @CheckSum = 'Y' SET @CurrentCommand += 'CHECKSUM' - IF @CheckSum = 'N' SET @CurrentCommand += 'NO_CHECKSUM' - - IF @Version >= 10 - BEGIN - SET @CurrentCommand += CASE WHEN @Compress = 'Y' AND (@CurrentIsEncrypted = 0 OR (@CurrentIsEncrypted = 1 AND ((@Version >= 13 AND @CurrentMaxTransferSize >= 65537) OR @Version >= 15.0404316 OR SERVERPROPERTY('EngineEdition') = 8))) THEN ', COMPRESSION' ELSE ', NO_COMPRESSION' END - END - - IF @Compress = 'Y' AND @CompressionAlgorithm IS NOT NULL - BEGIN - SET @CurrentCommand += ' (ALGORITHM = ' + @CompressionAlgorithm + ')' - END - - IF @CurrentBackupType = 'DIFF' SET @CurrentCommand += ', DIFFERENTIAL' - - IF EXISTS(SELECT * FROM @CurrentFiles WHERE Mirror = 1) - BEGIN - SET @CurrentCommand += ', FORMAT' - END - - IF @CopyOnly = 'Y' SET @CurrentCommand += ', COPY_ONLY' - IF @NoRecovery = 'Y' AND @CurrentBackupType = 'LOG' SET @CurrentCommand += ', NORECOVERY' - IF @Init = 'Y' SET @CurrentCommand += ', INIT' - IF @Format = 'Y' SET @CurrentCommand += ', FORMAT' - IF @BlockSize IS NOT NULL SET @CurrentCommand += ', BLOCKSIZE = ' + CAST(@BlockSize AS nvarchar) - IF @BufferCount IS NOT NULL SET @CurrentCommand += ', BUFFERCOUNT = ' + CAST(@BufferCount AS nvarchar) - IF @CurrentMaxTransferSize IS NOT NULL SET @CurrentCommand += ', MAXTRANSFERSIZE = ' + CAST(@CurrentMaxTransferSize AS nvarchar) - IF @Description IS NOT NULL SET @CurrentCommand += ', DESCRIPTION = N''' + REPLACE(@Description,'''','''''') + '''' - IF @BackupOptions IS NOT NULL SET @CurrentCommand += ', BACKUP_OPTIONS = N''' + REPLACE(@BackupOptions,'''','''''') + '''' - IF @Encrypt = 'Y' SET @CurrentCommand += ', ENCRYPTION (ALGORITHM = ' + UPPER(@EncryptionAlgorithm) + ', ' - IF @Encrypt = 'Y' AND @ServerCertificate IS NOT NULL SET @CurrentCommand += 'SERVER CERTIFICATE = ' + QUOTENAME(@ServerCertificate) - IF @Encrypt = 'Y' AND @ServerAsymmetricKey IS NOT NULL SET @CurrentCommand += 'SERVER ASYMMETRIC KEY = ' + QUOTENAME(@ServerAsymmetricKey) - IF @Encrypt = 'Y' SET @CurrentCommand += ')' - IF @URL IS NOT NULL AND @Credential IS NOT NULL SET @CurrentCommand += ', CREDENTIAL = N''' + REPLACE(@Credential,'''','''''') + '''' - END - END + SET @CurrentCommand += ' TO' + + SELECT @CurrentCommand += ' ' + [Type] + ' = N''' + REPLACE(FilePath,'''','''''') + '''' + CASE WHEN ROW_NUMBER() OVER (ORDER BY FilePath ASC) <> @CurrentNumberOfFiles THEN ',' ELSE '' END + FROM @CurrentFiles + WHERE Mirror = 0 + ORDER BY FilePath ASC + + IF EXISTS(SELECT * FROM @CurrentFiles WHERE Mirror = 1) + BEGIN + SET @CurrentCommand += ' MIRROR TO' + + SELECT @CurrentCommand += ' ' + [Type] + ' = N''' + REPLACE(FilePath,'''','''''') + '''' + CASE WHEN ROW_NUMBER() OVER (ORDER BY FilePath ASC) <> @CurrentNumberOfFiles THEN ',' ELSE '' END + FROM @CurrentFiles + WHERE Mirror = 1 + ORDER BY FilePath ASC + END + + SET @CurrentCommand += ' WITH ' + IF @Checksum = 'Y' SET @CurrentCommand += 'CHECKSUM' + IF @Checksum = 'N' SET @CurrentCommand += 'NO_CHECKSUM' + + IF @Version >= 10 + BEGIN + SET @CurrentCommand += CASE WHEN @Compress = 'Y' AND (@CurrentIsEncrypted = 0 OR (@CurrentIsEncrypted = 1 AND ((@Version >= 13 AND @CurrentMaxTransferSize >= 65537) OR @Version >= 15.0404316 OR SERVERPROPERTY('EngineEdition') = 8))) THEN ', COMPRESSION' ELSE ', NO_COMPRESSION' END + END + + IF @Compress = 'Y' AND @CompressionAlgorithm IS NOT NULL + BEGIN + SET @CurrentCommand += ' (ALGORITHM = ' + @CompressionAlgorithm + ')' + END + + IF @CurrentBackupType = 'DIFF' SET @CurrentCommand += ', DIFFERENTIAL' + + IF EXISTS(SELECT * FROM @CurrentFiles WHERE Mirror = 1) + BEGIN + SET @CurrentCommand += ', FORMAT' + END + + IF @CopyOnly = 'Y' SET @CurrentCommand += ', COPY_ONLY' + IF @NoRecovery = 'Y' AND @CurrentBackupType = 'LOG' SET @CurrentCommand += ', NORECOVERY' + IF @Init = 'Y' SET @CurrentCommand += ', INIT' + IF @Format = 'Y' SET @CurrentCommand += ', FORMAT' + IF @BlockSize IS NOT NULL SET @CurrentCommand += ', BLOCKSIZE = ' + CAST(@BlockSize AS nvarchar) + IF @BufferCount IS NOT NULL SET @CurrentCommand += ', BUFFERCOUNT = ' + CAST(@BufferCount AS nvarchar) + IF @CurrentMaxTransferSize IS NOT NULL SET @CurrentCommand += ', MAXTRANSFERSIZE = ' + CAST(@CurrentMaxTransferSize AS nvarchar) + IF @Description IS NOT NULL SET @CurrentCommand += ', DESCRIPTION = N''' + REPLACE(@Description,'''','''''') + '''' + IF @BackupSetName IS NOT NULL SET @CurrentCommand += ', NAME = N''' + REPLACE(@BackupSetName,'''','''''') + '''' + IF @Stats IS NOT NULL SET @CurrentCommand += ', STATS = ' + CAST(@Stats AS nvarchar) + IF @BackupOptions IS NOT NULL SET @CurrentCommand += ', BACKUP_OPTIONS = N''' + REPLACE(@BackupOptions,'''','''''') + '''' + IF @Encrypt = 'Y' SET @CurrentCommand += ', ENCRYPTION (ALGORITHM = ' + UPPER(@EncryptionAlgorithm) + ', ' + IF @Encrypt = 'Y' AND @ServerCertificate IS NOT NULL SET @CurrentCommand += 'SERVER CERTIFICATE = ' + QUOTENAME(@ServerCertificate) + IF @Encrypt = 'Y' AND @ServerAsymmetricKey IS NOT NULL SET @CurrentCommand += 'SERVER ASYMMETRIC KEY = ' + QUOTENAME(@ServerAsymmetricKey) + IF @Encrypt = 'Y' SET @CurrentCommand += ')' + IF @URL IS NOT NULL AND @Credential IS NOT NULL SET @CurrentCommand += ', CREDENTIAL = N''' + REPLACE(@Credential,'''','''''') + '''' + IF @ExpireDate IS NOT NULL SET @CurrentCommand += ', EXPIREDATE = ''' + CONVERT(nvarchar, @ExpireDate, 21) + '''' + IF @RetainDays IS NOT NULL SET @CurrentCommand += ', RETAINDAYS = ' + CAST(@RetainDays AS nvarchar) + END + END IF @BackupSoftware = 'LITESPEED' BEGIN @@ -4353,8 +4450,8 @@ BEGIN END SET @CurrentCommand += ', @with = ''' - IF @CheckSum = 'Y' SET @CurrentCommand += 'CHECKSUM' - IF @CheckSum = 'N' SET @CurrentCommand += 'NO_CHECKSUM' + IF @Checksum = 'Y' SET @CurrentCommand += 'CHECKSUM' + IF @Checksum = 'N' SET @CurrentCommand += 'NO_CHECKSUM' IF @CurrentBackupType = 'DIFF' SET @CurrentCommand += ', DIFFERENTIAL' IF @CopyOnly = 'Y' SET @CurrentCommand += ', COPY_ONLY' IF @NoRecovery = 'Y' AND @CurrentBackupType = 'LOG' SET @CurrentCommand += ', NORECOVERY' @@ -4371,6 +4468,8 @@ BEGIN IF @Throttle IS NOT NULL SET @CurrentCommand += ', @throttle = ' + CAST(@Throttle AS nvarchar) IF @Description IS NOT NULL SET @CurrentCommand += ', @desc = N''' + REPLACE(@Description,'''','''''') + '''' IF @ObjectLevelRecoveryMap = 'Y' SET @CurrentCommand += ', @olrmap = 1' + IF @ExpireDate IS NOT NULL SET @CurrentCommand += ', @expiration = ''' + CONVERT(nvarchar, @ExpireDate, 21) + '''' + IF @RetainDays IS NOT NULL SET @CurrentCommand += ', @retaindays = ' + CAST(@RetainDays AS nvarchar) IF @EncryptionAlgorithm IS NOT NULL SET @CurrentCommand += ', @cryptlevel = ' + CASE WHEN @EncryptionAlgorithm = 'RC2_40' THEN '0' @@ -4415,8 +4514,8 @@ BEGIN SET @CurrentCommand += ' MIRRORFILE' + ' = N''' + REPLACE((SELECT FilePath FROM @CurrentFiles WHERE Mirror = 1),'''','''''') + ''', ' END - IF @CheckSum = 'Y' SET @CurrentCommand += 'CHECKSUM' - IF @CheckSum = 'N' SET @CurrentCommand += 'NO_CHECKSUM' + IF @Checksum = 'Y' SET @CurrentCommand += 'CHECKSUM' + IF @Checksum = 'N' SET @CurrentCommand += 'NO_CHECKSUM' IF @CurrentBackupType = 'DIFF' SET @CurrentCommand += ', DIFFERENTIAL' IF @CopyOnly = 'Y' SET @CurrentCommand += ', COPY_ONLY' IF @NoRecovery = 'Y' AND @CurrentBackupType = 'LOG' SET @CurrentCommand += ', NORECOVERY' @@ -4456,7 +4555,7 @@ BEGIN SET @CurrentCommand += ', @backuptype = ' + CASE WHEN @CurrentBackupType = 'FULL' THEN '''Full''' WHEN @CurrentBackupType = 'DIFF' THEN '''Differential''' WHEN @CurrentBackupType = 'LOG' THEN '''Log''' END IF @ReadWriteFileGroups = 'Y' AND @CurrentDatabaseName <> 'master' SET @CurrentCommand += ', @readwritefilegroups = 1' - SET @CurrentCommand += ', @checksum = ' + CASE WHEN @CheckSum = 'Y' THEN '1' WHEN @CheckSum = 'N' THEN '0' END + SET @CurrentCommand += ', @checksum = ' + CASE WHEN @Checksum = 'Y' THEN '1' WHEN @Checksum = 'N' THEN '0' END SET @CurrentCommand += ', @copyonly = ' + CASE WHEN @CopyOnly = 'Y' THEN '1' WHEN @CopyOnly = 'N' THEN '0' END IF @CompressionLevel IS NOT NULL SET @CurrentCommand += ', @compressionlevel = ' + CAST(@CompressionLevel AS nvarchar) IF @Threads IS NOT NULL SET @CurrentCommand += ', @threads = ' + CAST(@Threads AS nvarchar) @@ -4480,7 +4579,7 @@ BEGIN SET @CurrentCommand = 'DECLARE @ReturnCode int EXECUTE @ReturnCode = dbo.emc_run_backup ''' - SET @CurrentCommand += ' -c ' + CASE WHEN @CurrentAvailabilityGroup IS NOT NULL THEN @Cluster ELSE CAST(SERVERPROPERTY('MachineName') AS nvarchar) END + SET @CurrentCommand += ' -c ' + CASE WHEN @Cluster IS NOT NULL AND @CurrentAvailabilityGroup IS NOT NULL THEN @Cluster ELSE CAST(SERVERPROPERTY('MachineName') AS nvarchar) END SET @CurrentCommand += ' -l ' + CASE WHEN @CurrentBackupType = 'FULL' THEN 'full' @@ -4492,7 +4591,7 @@ BEGIN IF @CleanupTime IS NOT NULL SET @CurrentCommand += ' -y +' + CAST(@CleanupTime/24 + CASE WHEN @CleanupTime%24 > 0 THEN 1 ELSE 0 END AS nvarchar) + 'd' - IF @CheckSum = 'Y' SET @CurrentCommand += ' -k' + IF @Checksum = 'Y' SET @CurrentCommand += ' -k' SET @CurrentCommand += ' -S ' + CAST(@CurrentNumberOfFiles AS nvarchar) @@ -4509,9 +4608,11 @@ BEGIN SET @CurrentCommand += ' -a "NSR_SKIP_NON_BACKUPABLE_STATE_DB=TRUE"' SET @CurrentCommand += ' -a "BACKUP_PROMOTION=NONE"' IF @CopyOnly = 'Y' SET @CurrentCommand += ' -a "NSR_COPY_ONLY=TRUE"' + IF @BackupSetName IS NOT NULL SET @CurrentCommand += ' -N "' + REPLACE(@BackupSetName,'''','''''') + '"' - IF SERVERPROPERTY('InstanceName') IS NULL SET @CurrentCommand += ' "MSSQL' + ':' + REPLACE(REPLACE(@CurrentDatabaseName,'''',''''''),'.','\.') + '"' - IF SERVERPROPERTY('InstanceName') IS NOT NULL SET @CurrentCommand += ' "MSSQL$' + CAST(SERVERPROPERTY('InstanceName') AS nvarchar) + ':' + REPLACE(REPLACE(@CurrentDatabaseName,'''',''''''),'.','\.') + '"' + IF SERVERPROPERTY('InstanceName') IS NULL SET @CurrentCommand += ' "MSSQL' + IF SERVERPROPERTY('InstanceName') IS NOT NULL SET @CurrentCommand += ' "MSSQL$' + CAST(SERVERPROPERTY('InstanceName') AS nvarchar) + SET @CurrentCommand += ':' + REPLACE(REPLACE(@CurrentDatabaseName,'''',''''''),'.','\.') + '"' SET @CurrentCommand += '''' @@ -4559,8 +4660,9 @@ BEGIN ORDER BY FilePath ASC SET @CurrentCommand += ' WITH ' - IF @CheckSum = 'Y' SET @CurrentCommand += 'CHECKSUM' - IF @CheckSum = 'N' SET @CurrentCommand += 'NO_CHECKSUM' + IF @Checksum = 'Y' SET @CurrentCommand += 'CHECKSUM' + IF @Checksum = 'N' SET @CurrentCommand += 'NO_CHECKSUM' + IF @Stats IS NOT NULL SET @CurrentCommand += ', STATS = ' + CAST(@Stats AS nvarchar) IF @BackupOptions IS NOT NULL SET @CurrentCommand += ', RESTORE_OPTIONS = N''' + REPLACE(@BackupOptions,'''','''''') + '''' IF @URL IS NOT NULL AND @Credential IS NOT NULL SET @CurrentCommand += ', CREDENTIAL = N''' + REPLACE(@Credential,'''','''''') + '''' END @@ -4579,8 +4681,8 @@ BEGIN ORDER BY FilePath ASC SET @CurrentCommand += ', @with = ''' - IF @CheckSum = 'Y' SET @CurrentCommand += 'CHECKSUM' - IF @CheckSum = 'N' SET @CurrentCommand += 'NO_CHECKSUM' + IF @Checksum = 'Y' SET @CurrentCommand += 'CHECKSUM' + IF @Checksum = 'N' SET @CurrentCommand += 'NO_CHECKSUM' SET @CurrentCommand += '''' IF @EncryptionKey IS NOT NULL SET @CurrentCommand += ', @encryptionkey = N''' + REPLACE(@EncryptionKey,'''','''''') + '''' @@ -4601,8 +4703,8 @@ BEGIN ORDER BY FilePath ASC SET @CurrentCommand += ' WITH ' - IF @CheckSum = 'Y' SET @CurrentCommand += 'CHECKSUM' - IF @CheckSum = 'N' SET @CurrentCommand += 'NO_CHECKSUM' + IF @Checksum = 'Y' SET @CurrentCommand += 'CHECKSUM' + IF @Checksum = 'N' SET @CurrentCommand += 'NO_CHECKSUM' IF @EncryptionKey IS NOT NULL SET @CurrentCommand += ', PASSWORD = N''' + REPLACE(@EncryptionKey,'''','''''') + '''' SET @CurrentCommand = 'DECLARE @ReturnCode int EXECUTE @ReturnCode = dbo.sqlbackup N''-SQL "' + REPLACE(@CurrentCommand,'''','''''') + '"''' + ' IF @ReturnCode <> 0 RAISERROR(''Error verifying SQLBackup backup.'', 16, 1)' @@ -4803,6 +4905,7 @@ BEGIN SET @CurrentDifferentialBaseLSN = NULL SET @CurrentDifferentialBaseIsSnapshot = NULL SET @CurrentLogLSN = NULL + SET @BackupInProcess = NULL SET @CurrentLatestBackup = NULL SET @CurrentDatabaseNameFS = NULL SET @CurrentDirectoryStructure = NULL @@ -4811,7 +4914,6 @@ BEGIN SET @CurrentDate = NULL SET @CurrentDateUTC = NULL SET @CurrentCleanupDate = NULL - SET @CurrentIsDatabaseAccessible = NULL SET @CurrentReplicaID = NULL SET @CurrentAvailabilityGroupID = NULL SET @CurrentAvailabilityGroup = NULL @@ -4859,7 +4961,6 @@ BEGIN END GO - SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON @@ -4877,6 +4978,7 @@ ALTER PROCEDURE [dbo].[DatabaseIntegrityCheck] @DataPurity nvarchar(max) = 'N', @NoIndex nvarchar(max) = 'N', @ExtendedLogicalChecks nvarchar(max) = 'N', +@NoInformationalMessages nvarchar(max) = 'N', @TabLock nvarchar(max) = 'N', @FileGroups nvarchar(max) = NULL, @Objects nvarchar(max) = NULL, @@ -4901,7 +5003,7 @@ BEGIN --// Source: https://ola.hallengren.com //-- --// License: https://ola.hallengren.com/license.html //-- --// GitHub: https://github.com/olahallengren/sql-server-maintenance-solution //-- - --// Version: 2024-12-27 18:10:28 //-- + --// Version: 2025-02-19 21:12:35 //-- ---------------------------------------------------------------------------------------------------- SET NOCOUNT ON @@ -4934,7 +5036,6 @@ BEGIN DECLARE @CurrentInStandby bit DECLARE @CurrentRecoveryModel nvarchar(max) - DECLARE @CurrentIsDatabaseAccessible bit DECLARE @CurrentReplicaID uniqueidentifier DECLARE @CurrentAvailabilityGroupID uniqueidentifier DECLARE @CurrentAvailabilityGroup nvarchar(max) @@ -5054,7 +5155,7 @@ BEGIN SET @HostPlatform = 'Windows' END - DECLARE @AmazonRDS bit = CASE WHEN DB_ID('rdsadmin') IS NOT NULL AND SUSER_SNAME(0x01) = 'rdsa' THEN 1 ELSE 0 END + DECLARE @AmazonRDS bit = CASE WHEN SERVERPROPERTY('EngineEdition') IN (5, 8) THEN 0 WHEN EXISTS (SELECT * FROM sys.databases WHERE [name] = 'rdsadmin') AND SUSER_SNAME(0x01) = 'rdsa' THEN 1 ELSE 0 END ---------------------------------------------------------------------------------------------------- --// Log initial information //-- @@ -5066,6 +5167,7 @@ BEGIN SET @Parameters += ', @DataPurity = ' + ISNULL('''' + REPLACE(@DataPurity,'''','''''') + '''','NULL') SET @Parameters += ', @NoIndex = ' + ISNULL('''' + REPLACE(@NoIndex,'''','''''') + '''','NULL') SET @Parameters += ', @ExtendedLogicalChecks = ' + ISNULL('''' + REPLACE(@ExtendedLogicalChecks,'''','''''') + '''','NULL') + SET @Parameters += ', @NoInformationalMessages = ' + ISNULL('''' + REPLACE(@NoInformationalMessages,'''','''''') + '''','NULL') SET @Parameters += ', @TabLock = ' + ISNULL('''' + REPLACE(@TabLock,'''','''''') + '''','NULL') SET @Parameters += ', @FileGroups = ' + ISNULL('''' + REPLACE(@FileGroups,'''','''''') + '''','NULL') SET @Parameters += ', @Objects = ' + ISNULL('''' + REPLACE(@Objects,'''','''''') + '''','NULL') @@ -5097,7 +5199,7 @@ BEGIN SET @StartMessage = 'Platform: ' + @HostPlatform RAISERROR('%s',10,1,@StartMessage) WITH NOWAIT - SET @StartMessage = 'Procedure: ' + QUOTENAME(DB_NAME(DB_ID())) + '.' + QUOTENAME(@SchemaName) + '.' + QUOTENAME(@ObjectName) + SET @StartMessage = 'Procedure: ' + QUOTENAME(DB_NAME()) + '.' + QUOTENAME(@SchemaName) + '.' + QUOTENAME(@ObjectName) RAISERROR('%s',10,1,@StartMessage) WITH NOWAIT SET @StartMessage = 'Parameters: ' + @Parameters @@ -5115,10 +5217,10 @@ BEGIN --// Check core requirements //-- ---------------------------------------------------------------------------------------------------- - IF NOT (SELECT [compatibility_level] FROM sys.databases WHERE database_id = DB_ID()) >= 90 + IF NOT (SELECT [compatibility_level] FROM sys.databases WHERE [name] = DB_NAME()) >= 90 BEGIN INSERT INTO @Errors ([Message], Severity, [State]) - SELECT 'The database ' + QUOTENAME(DB_NAME(DB_ID())) + ' has to be in compatibility level 90 or higher.', 16, 1 + SELECT 'The database ' + QUOTENAME(DB_NAME()) + ' has to be in compatibility level 90 or higher.', 16, 1 END IF NOT (SELECT uses_ansi_nulls FROM sys.sql_modules WHERE [object_id] = @@PROCID) = 1 @@ -5613,6 +5715,13 @@ BEGIN ---------------------------------------------------------------------------------------------------- + IF @NoInformationalMessages NOT IN ('Y','N') OR @NoInformationalMessages IS NULL + BEGIN + INSERT INTO @Errors ([Message], Severity, [State]) + SELECT 'The value for the parameter @NoInformationalMessages is not supported.', 16, 1 + END + + ---------------------------------------------------------------------------------------------------- IF @TabLock NOT IN ('Y','N') OR @TabLock IS NULL BEGIN INSERT INTO @Errors ([Message], Severity, [State]) @@ -6218,20 +6327,8 @@ BEGIN SET @DatabaseMessage = 'Recovery model: ' + @CurrentRecoveryModel RAISERROR('%s',10,1,@DatabaseMessage) WITH NOWAIT END - - IF @CurrentDatabaseState IN('ONLINE','EMERGENCY') AND SERVERPROPERTY('EngineEdition') <> 5 - BEGIN - IF EXISTS (SELECT * FROM sys.database_recovery_status WHERE database_id = DB_ID(@CurrentDatabaseName) AND database_guid IS NOT NULL) - BEGIN - SET @CurrentIsDatabaseAccessible = 1 - END - ELSE - BEGIN - SET @CurrentIsDatabaseAccessible = 0 - END - END - - IF @Version >= 11 AND SERVERPROPERTY('IsHadrEnabled') = 1 + + IF @Version >= 11 AND SERVERPROPERTY('IsHadrEnabled') = 1 BEGIN SELECT @CurrentReplicaID = databases.replica_id FROM sys.databases databases @@ -6261,17 +6358,12 @@ BEGIN IF SERVERPROPERTY('EngineEdition') <> 5 BEGIN SELECT @CurrentDatabaseMirroringRole = UPPER(mirroring_role_desc) - FROM sys.database_mirroring - WHERE database_id = DB_ID(@CurrentDatabaseName) - END - - IF @CurrentIsDatabaseAccessible IS NOT NULL - BEGIN - SET @DatabaseMessage = 'Is accessible: ' + CASE WHEN @CurrentIsDatabaseAccessible = 1 THEN 'Yes' ELSE 'No' END - RAISERROR('%s',10,1,@DatabaseMessage) WITH NOWAIT + FROM sys.database_mirroring database_mirroring + INNER JOIN sys.databases databases ON database_mirroring.database_id = databases.database_id + WHERE databases.[name] = @CurrentDatabaseName END - - IF @CurrentAvailabilityGroup IS NOT NULL + + IF @CurrentAvailabilityGroup IS NOT NULL BEGIN SET @DatabaseMessage = 'Availability group: ' + ISNULL(@CurrentAvailabilityGroup,'N/A') RAISERROR('%s',10,1,@DatabaseMessage) WITH NOWAIT @@ -6304,11 +6396,12 @@ BEGIN RAISERROR(@EmptyLine,10,1) WITH NOWAIT IF @CurrentDatabaseState IN('ONLINE','EMERGENCY') - AND NOT (@CurrentUserAccess = 'SINGLE_USER' AND @CurrentIsDatabaseAccessible = 0) + AND NOT (@CurrentUserAccess = 'SINGLE_USER') AND (@CurrentAvailabilityGroupRole = 'PRIMARY' OR @CurrentAvailabilityGroupRole IS NULL OR SERVERPROPERTY('EngineEdition') = 3) AND ((@AvailabilityGroupReplicas = 'PRIMARY' AND @CurrentAvailabilityGroupRole = 'PRIMARY') OR (@AvailabilityGroupReplicas = 'SECONDARY' AND @CurrentAvailabilityGroupRole = 'SECONDARY') OR (@AvailabilityGroupReplicas = 'PREFERRED_BACKUP_REPLICA' AND @CurrentIsPreferredBackupReplica = 1) OR @AvailabilityGroupReplicas = 'ALL' OR @CurrentAvailabilityGroupRole IS NULL) AND NOT (@CurrentIsReadOnly = 1 AND @Updateability = 'READ_WRITE') AND NOT (@CurrentIsReadOnly = 0 AND @Updateability = 'READ_ONLY') + AND NOT (@AmazonRDS = 1 AND @CurrentDatabaseName = 'rdsadmin') BEGIN -- Check database @@ -6322,10 +6415,11 @@ BEGIN IF @LockTimeout IS NOT NULL SET @CurrentCommand = 'SET LOCK_TIMEOUT ' + CAST(@LockTimeout * 1000 AS nvarchar) + '; ' SET @CurrentCommand += 'DBCC CHECKDB (' + QUOTENAME(@CurrentDatabaseName) IF @NoIndex = 'Y' SET @CurrentCommand += ', NOINDEX' - SET @CurrentCommand += ') WITH NO_INFOMSGS, ALL_ERRORMSGS' + SET @CurrentCommand += ') WITH ALL_ERRORMSGS' IF @DataPurity = 'Y' SET @CurrentCommand += ', DATA_PURITY' IF @PhysicalOnly = 'Y' SET @CurrentCommand += ', PHYSICAL_ONLY' IF @ExtendedLogicalChecks = 'Y' SET @CurrentCommand += ', EXTENDED_LOGICAL_CHECKS' + IF @NoInformationalMessages = 'Y' SET @CurrentCommand += ', NO_INFOMSGS' IF @TabLock = 'Y' SET @CurrentCommand += ', TABLOCK' IF @MaxDOP IS NOT NULL SET @CurrentCommand += ', MAXDOP = ' + CAST(@MaxDOP AS nvarchar) @@ -6450,8 +6544,9 @@ BEGIN IF @LockTimeout IS NOT NULL SET @CurrentCommand = 'SET LOCK_TIMEOUT ' + CAST(@LockTimeout * 1000 AS nvarchar) + '; ' SET @CurrentCommand += 'DBCC CHECKFILEGROUP (' + QUOTENAME(@CurrentFileGroupName) IF @NoIndex = 'Y' SET @CurrentCommand += ', NOINDEX' - SET @CurrentCommand += ') WITH NO_INFOMSGS, ALL_ERRORMSGS' + SET @CurrentCommand += ') WITH ALL_ERRORMSGS' IF @PhysicalOnly = 'Y' SET @CurrentCommand += ', PHYSICAL_ONLY' + IF @NoInformationalMessages = 'Y' SET @CurrentCommand += ', NO_INFOMSGS' IF @TabLock = 'Y' SET @CurrentCommand += ', TABLOCK' IF @MaxDOP IS NOT NULL SET @CurrentCommand += ', MAXDOP = ' + CAST(@MaxDOP AS nvarchar) @@ -6489,7 +6584,8 @@ BEGIN SET @CurrentCommand = '' IF @LockTimeout IS NOT NULL SET @CurrentCommand = 'SET LOCK_TIMEOUT ' + CAST(@LockTimeout * 1000 AS nvarchar) + '; ' SET @CurrentCommand += 'DBCC CHECKALLOC (' + QUOTENAME(@CurrentDatabaseName) - SET @CurrentCommand += ') WITH NO_INFOMSGS, ALL_ERRORMSGS' + SET @CurrentCommand += ') WITH ALL_ERRORMSGS' + IF @NoInformationalMessages = 'Y' SET @CurrentCommand += ', NO_INFOMSGS' IF @TabLock = 'Y' SET @CurrentCommand += ', TABLOCK' EXECUTE @CurrentCommandOutput = dbo.CommandExecute @DatabaseContext = @CurrentDatabaseContext, @Command = @CurrentCommand, @CommandType = @CurrentCommandType, @Mode = 1, @DatabaseName = @CurrentDatabaseName, @LogToTable = @LogToTable, @Execute = @Execute @@ -6617,10 +6713,11 @@ BEGIN IF @LockTimeout IS NOT NULL SET @CurrentCommand = 'SET LOCK_TIMEOUT ' + CAST(@LockTimeout * 1000 AS nvarchar) + '; ' SET @CurrentCommand += 'DBCC CHECKTABLE (' + QUOTENAME(QUOTENAME(@CurrentSchemaName) + '.' + QUOTENAME(@CurrentObjectName),'''') IF @NoIndex = 'Y' SET @CurrentCommand += ', NOINDEX' - SET @CurrentCommand += ') WITH NO_INFOMSGS, ALL_ERRORMSGS' + SET @CurrentCommand += ') WITH ALL_ERRORMSGS' IF @DataPurity = 'Y' SET @CurrentCommand += ', DATA_PURITY' IF @PhysicalOnly = 'Y' SET @CurrentCommand += ', PHYSICAL_ONLY' IF @ExtendedLogicalChecks = 'Y' SET @CurrentCommand += ', EXTENDED_LOGICAL_CHECKS' + IF @NoInformationalMessages = 'Y' SET @CurrentCommand += ', NO_INFOMSGS' IF @TabLock = 'Y' SET @CurrentCommand += ', TABLOCK' IF @MaxDOP IS NOT NULL SET @CurrentCommand += ', MAXDOP = ' + CAST(@MaxDOP AS nvarchar) @@ -6661,7 +6758,8 @@ BEGIN SET @CurrentCommand = '' IF @LockTimeout IS NOT NULL SET @CurrentCommand = 'SET LOCK_TIMEOUT ' + CAST(@LockTimeout * 1000 AS nvarchar) + '; ' SET @CurrentCommand += 'DBCC CHECKCATALOG (' + QUOTENAME(@CurrentDatabaseName) - SET @CurrentCommand += ') WITH NO_INFOMSGS' + SET @CurrentCommand += ')' + IF @NoInformationalMessages = 'Y' SET @CurrentCommand += ' WITH NO_INFOMSGS' EXECUTE @CurrentCommandOutput = dbo.CommandExecute @DatabaseContext = @CurrentDatabaseContext, @Command = @CurrentCommand, @CommandType = @CurrentCommandType, @Mode = 1, @DatabaseName = @CurrentDatabaseName, @LogToTable = @LogToTable, @Execute = @Execute SET @Error = @@ERROR @@ -6708,7 +6806,6 @@ BEGIN SET @CurrentInStandby = NULL SET @CurrentRecoveryModel = NULL - SET @CurrentIsDatabaseAccessible = NULL SET @CurrentReplicaID = NULL SET @CurrentAvailabilityGroupID = NULL SET @CurrentAvailabilityGroup = NULL @@ -6803,7 +6900,7 @@ BEGIN --// Source: https://ola.hallengren.com //-- --// License: https://ola.hallengren.com/license.html //-- --// GitHub: https://github.com/olahallengren/sql-server-maintenance-solution //-- - --// Version: 2024-12-27 18:10:28 //-- + --// Version: 2025-02-19 21:12:35 //-- ---------------------------------------------------------------------------------------------------- SET NOCOUNT ON @@ -6843,7 +6940,6 @@ BEGIN DECLARE @CurrentInStandby bit DECLARE @CurrentRecoveryModel nvarchar(max) - DECLARE @CurrentIsDatabaseAccessible bit DECLARE @CurrentReplicaID uniqueidentifier DECLARE @CurrentAvailabilityGroupID uniqueidentifier DECLARE @CurrentAvailabilityGroup nvarchar(max) @@ -6888,10 +6984,12 @@ BEGIN DECLARE @CurrentIsImageText bit DECLARE @CurrentIsNewLOB bit DECLARE @CurrentIsFileStream bit - DECLARE @CurrentIsColumnStore bit + DECLARE @CurrentHasColumnstore bit DECLARE @CurrentIsComputed bit + DECLARE @CurrentIsClusteredIndexComputed bit DECLARE @CurrentIsTimestamp bit DECLARE @CurrentAllowPageLocks bit + DECLARE @CurrentHasFilter bit DECLARE @CurrentNoRecompute bit DECLARE @CurrentIsIncremental bit DECLARE @CurrentRowCount bigint @@ -6938,11 +7036,13 @@ BEGIN IndexName nvarchar(max), IndexType int, AllowPageLocks bit, + HasFilter bit, IsImageText bit, IsNewLOB bit, IsFileStream bit, - IsColumnStore bit, + HasColumnstore bit, IsComputed bit, + IsClusteredIndexComputed bit, IsTimestamp bit, OnReadOnlyFileGroup bit, ResumableIndexOperation bit, @@ -7021,7 +7121,7 @@ BEGIN SET @HostPlatform = 'Windows' END - DECLARE @AmazonRDS bit = CASE WHEN DB_ID('rdsadmin') IS NOT NULL AND SUSER_SNAME(0x01) = 'rdsa' THEN 1 ELSE 0 END + DECLARE @AmazonRDS bit = CASE WHEN SERVERPROPERTY('EngineEdition') IN (5, 8) THEN 0 WHEN EXISTS (SELECT * FROM sys.databases WHERE [name] = 'rdsadmin') AND SUSER_SNAME(0x01) = 'rdsa' THEN 1 ELSE 0 END ---------------------------------------------------------------------------------------------------- --// Log initial information //-- @@ -7078,7 +7178,7 @@ BEGIN SET @StartMessage = 'Platform: ' + @HostPlatform RAISERROR('%s',10,1,@StartMessage) WITH NOWAIT - SET @StartMessage = 'Procedure: ' + QUOTENAME(DB_NAME(DB_ID())) + '.' + QUOTENAME(@SchemaName) + '.' + QUOTENAME(@ObjectName) + SET @StartMessage = 'Procedure: ' + QUOTENAME(DB_NAME()) + '.' + QUOTENAME(@SchemaName) + '.' + QUOTENAME(@ObjectName) RAISERROR('%s',10,1,@StartMessage) WITH NOWAIT SET @StartMessage = 'Parameters: ' + @Parameters @@ -7096,10 +7196,10 @@ BEGIN --// Check core requirements //-- ---------------------------------------------------------------------------------------------------- - IF NOT (SELECT [compatibility_level] FROM sys.databases WHERE database_id = DB_ID()) >= 90 + IF NOT (SELECT [compatibility_level] FROM sys.databases WHERE [name] = DB_NAME()) >= 90 BEGIN INSERT INTO @Errors ([Message], Severity, [State]) - SELECT 'The database ' + QUOTENAME(DB_NAME(DB_ID())) + ' has to be in compatibility level 90 or higher.', 16, 1 + SELECT 'The database ' + QUOTENAME(DB_NAME()) + ' has to be in compatibility level 90 or higher.', 16, 1 END IF NOT (SELECT uses_ansi_nulls FROM sys.sql_modules WHERE [object_id] = @@PROCID) = 1 @@ -8180,14 +8280,6 @@ BEGIN SET @CurrentDatabase_sp_executesql = QUOTENAME(@CurrentDatabaseName) + '.sys.sp_executesql' - IF @ExecuteAsUser IS NOT NULL - BEGIN - SET @CurrentCommand = '' - SET @CurrentCommand += 'IF EXISTS(SELECT * FROM sys.database_principals database_principals WHERE database_principals.[name] = @ParamExecuteAsUser) BEGIN SET @ParamExecuteAsUserExists = 1 END ELSE BEGIN SET @ParamExecuteAsUserExists = 0 END' - - EXECUTE @CurrentDatabase_sp_executesql @stmt = @CurrentCommand, @params = N'@ParamExecuteAsUser sysname, @ParamExecuteAsUserExists bit OUTPUT', @ParamExecuteAsUser = @ExecuteAsUser, @ParamExecuteAsUserExists = @CurrentExecuteAsUserExists OUTPUT - END - BEGIN SET @DatabaseMessage = 'Date and time: ' + CONVERT(nvarchar,SYSDATETIME(),120) RAISERROR('%s',10,1,@DatabaseMessage) WITH NOWAIT @@ -8221,18 +8313,6 @@ BEGIN RAISERROR('%s',10,1,@DatabaseMessage) WITH NOWAIT END - IF @CurrentDatabaseState = 'ONLINE' AND SERVERPROPERTY('EngineEdition') <> 5 - BEGIN - IF EXISTS (SELECT * FROM sys.database_recovery_status WHERE database_id = DB_ID(@CurrentDatabaseName) AND database_guid IS NOT NULL) - BEGIN - SET @CurrentIsDatabaseAccessible = 1 - END - ELSE - BEGIN - SET @CurrentIsDatabaseAccessible = 0 - END - END - IF @Version >= 11 AND SERVERPROPERTY('IsHadrEnabled') = 1 BEGIN SELECT @CurrentReplicaID = databases.replica_id @@ -8256,14 +8336,9 @@ BEGIN IF SERVERPROPERTY('EngineEdition') <> 5 BEGIN SELECT @CurrentDatabaseMirroringRole = UPPER(mirroring_role_desc) - FROM sys.database_mirroring - WHERE database_id = DB_ID(@CurrentDatabaseName) - END - - IF @CurrentIsDatabaseAccessible IS NOT NULL - BEGIN - SET @DatabaseMessage = 'Is accessible: ' + CASE WHEN @CurrentIsDatabaseAccessible = 1 THEN 'Yes' ELSE 'No' END - RAISERROR('%s',10,1,@DatabaseMessage) WITH NOWAIT + FROM sys.database_mirroring database_mirroring + INNER JOIN sys.databases databases ON database_mirroring.database_id = databases.database_id + WHERE databases.[name] = @CurrentDatabaseName END IF @CurrentAvailabilityGroup IS NOT NULL @@ -8282,7 +8357,17 @@ BEGIN END RAISERROR(@EmptyLine,10,1) WITH NOWAIT + IF @ExecuteAsUser IS NOT NULL + AND @CurrentDatabaseState = 'ONLINE' + AND NOT (@CurrentUserAccess = 'SINGLE_USER') + AND NOT (@CurrentAvailabilityGroup IS NOT NULL AND (@CurrentAvailabilityGroupRole <> 'PRIMARY' OR @CurrentAvailabilityGroupRole IS NULL)) + AND NOT (@AmazonRDS = 1 AND @CurrentDatabaseName = 'rdsadmin') + BEGIN + SET @CurrentCommand = '' + SET @CurrentCommand += 'IF EXISTS(SELECT * FROM sys.database_principals database_principals WHERE database_principals.[name] = @ParamExecuteAsUser) BEGIN SET @ParamExecuteAsUserExists = 1 END ELSE BEGIN SET @ParamExecuteAsUserExists = 0 END' + EXECUTE @CurrentDatabase_sp_executesql @stmt = @CurrentCommand, @params = N'@ParamExecuteAsUser sysname, @ParamExecuteAsUserExists bit OUTPUT', @ParamExecuteAsUser = @ExecuteAsUser, @ParamExecuteAsUserExists = @CurrentExecuteAsUserExists OUTPUT + END IF @CurrentExecuteAsUserExists = 0 BEGIN SET @DatabaseMessage = 'The user ' + QUOTENAME(@ExecuteAsUser) + ' does not exist in the database ' + QUOTENAME(@CurrentDatabaseName) + '.' @@ -8291,8 +8376,10 @@ BEGIN END IF @CurrentDatabaseState = 'ONLINE' - AND NOT (@CurrentUserAccess = 'SINGLE_USER' AND @CurrentIsDatabaseAccessible = 0) - AND DATABASEPROPERTYEX(@CurrentDatabaseName,'Updateability') = 'READ_WRITE' + AND NOT (@CurrentUserAccess = 'SINGLE_USER') + AND NOT (@CurrentAvailabilityGroup IS NOT NULL AND (@CurrentAvailabilityGroupRole <> 'PRIMARY' OR @CurrentAvailabilityGroupRole IS NULL)) + AND NOT (@AmazonRDS = 1 AND @CurrentDatabaseName = 'rdsadmin') + AND NOT (@CurrentIsReadOnly = 1) AND (@CurrentExecuteAsUserExists = 1 OR @CurrentExecuteAsUserExists IS NULL) BEGIN @@ -8300,7 +8387,7 @@ BEGIN IF (EXISTS(SELECT * FROM @ActionsPreferred) OR @UpdateStatistics IS NOT NULL) AND (SYSDATETIME() < DATEADD(SECOND,@TimeLimit,@StartTime) OR @TimeLimit IS NULL) BEGIN SET @CurrentCommand = 'SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;' - + ' SELECT SchemaID, SchemaName, ObjectID, ObjectName, ObjectType, IsMemoryOptimized, IndexID, IndexName, IndexType, AllowPageLocks, IsImageText, IsNewLOB, IsFileStream, IsColumnStore, IsComputed, IsTimestamp, OnReadOnlyFileGroup, ResumableIndexOperation, StatisticsID, StatisticsName, NoRecompute, IsIncremental, PartitionID, PartitionNumber, PartitionCount, [Order], Selected, Completed' + + ' SELECT SchemaID, SchemaName, ObjectID, ObjectName, ObjectType, IsMemoryOptimized, IndexID, IndexName, IndexType, AllowPageLocks, HasFilter, IsImageText, IsNewLOB, IsFileStream, HasColumnstore, IsComputed, IsClusteredIndexComputed, IsTimestamp, OnReadOnlyFileGroup, ResumableIndexOperation, StatisticsID, StatisticsName, NoRecompute, IsIncremental, PartitionID, PartitionNumber, PartitionCount, [Order], Selected, Completed' + ' FROM (' IF EXISTS(SELECT * FROM @ActionsPreferred) OR @UpdateStatistics IN('ALL','INDEX') @@ -8315,6 +8402,7 @@ BEGIN + ', indexes.[name] AS IndexName' + ', indexes.[type] AS IndexType' + ', indexes.allow_page_locks AS AllowPageLocks' + + ', indexes.has_filter AS HasFilter' + ', CASE WHEN indexes.[type] = 1 AND EXISTS(SELECT * FROM sys.columns columns INNER JOIN sys.types types ON columns.system_type_id = types.user_type_id WHERE columns.[object_id] = objects.object_id AND types.name IN(''image'',''text'',''ntext'')) THEN 1 ELSE 0 END AS IsImageText' @@ -8323,17 +8411,18 @@ BEGIN + ', CASE WHEN indexes.[type] = 1 AND EXISTS(SELECT * FROM sys.columns columns WHERE columns.[object_id] = objects.object_id AND columns.is_filestream = 1) THEN 1 ELSE 0 END AS IsFileStream' - + ', CASE WHEN EXISTS(SELECT * FROM sys.indexes indexes WHERE indexes.[object_id] = objects.object_id AND [type] IN(5,6)) THEN 1 ELSE 0 END AS IsColumnStore' + + ', CASE WHEN EXISTS(SELECT * FROM sys.indexes indexes WHERE indexes.[object_id] = objects.object_id AND [type] IN(5,6)) THEN 1 ELSE 0 END AS HasColumnstore' + ', CASE WHEN EXISTS(SELECT * FROM sys.index_columns index_columns INNER JOIN sys.columns columns ON index_columns.object_id = columns.object_id AND index_columns.column_id = columns.column_id WHERE (index_columns.key_ordinal > 0 OR index_columns.partition_ordinal > 0) AND columns.is_computed = 1 AND index_columns.object_id = indexes.object_id AND index_columns.index_id = indexes.index_id) THEN 1 ELSE 0 END AS IsComputed' + + ', CASE WHEN EXISTS(SELECT * FROM sys.index_columns index_columns INNER JOIN sys.columns columns ON index_columns.object_id = columns.object_id AND index_columns.column_id = columns.column_id INNER JOIN sys.indexes indexes2 ON index_columns.object_id = indexes2.object_id AND index_columns.index_id = indexes2.index_id WHERE (index_columns.key_ordinal > 0 OR index_columns.partition_ordinal > 0) AND columns.is_computed = 1 AND indexes2.[type] = 1 AND index_columns.object_id = indexes.object_id) THEN 1 ELSE 0 END AS IsClusteredIndexComputed' + ', CASE WHEN EXISTS(SELECT * FROM sys.index_columns index_columns INNER JOIN sys.columns columns ON index_columns.[object_id] = columns.[object_id] AND index_columns.column_id = columns.column_id INNER JOIN sys.types types ON columns.system_type_id = types.system_type_id WHERE index_columns.[object_id] = objects.object_id AND index_columns.index_id = indexes.index_id AND types.[name] = ''timestamp'') THEN 1 ELSE 0 END AS IsTimestamp' + ', CASE WHEN EXISTS (SELECT * FROM sys.indexes indexes2 INNER JOIN sys.destination_data_spaces destination_data_spaces ON indexes.data_space_id = destination_data_spaces.partition_scheme_id INNER JOIN sys.filegroups filegroups ON destination_data_spaces.data_space_id = filegroups.data_space_id WHERE filegroups.is_read_only = 1 AND indexes2.[object_id] = indexes.[object_id] AND indexes2.[index_id] = indexes.index_id' + CASE WHEN @PartitionLevel = 'Y' THEN ' AND destination_data_spaces.destination_id = partitions.partition_number' ELSE '' END + ') THEN 1' + ' WHEN EXISTS (SELECT * FROM sys.indexes indexes2 INNER JOIN sys.filegroups filegroups ON indexes.data_space_id = filegroups.data_space_id WHERE filegroups.is_read_only = 1 AND indexes.[object_id] = indexes2.[object_id] AND indexes.[index_id] = indexes2.index_id) THEN 1' + ' WHEN indexes.[type] = 1 AND EXISTS (SELECT * FROM sys.tables tables INNER JOIN sys.filegroups filegroups ON tables.lob_data_space_id = filegroups.data_space_id WHERE filegroups.is_read_only = 1 AND tables.[object_id] = objects.[object_id]) THEN 1 ELSE 0 END AS OnReadOnlyFileGroup' - + ', ' + CASE WHEN @Version >= 14 THEN 'CASE WHEN EXISTS(SELECT * FROM sys.index_resumable_operations index_resumable_operations WHERE state_desc = ''PAUSED'' AND index_resumable_operations.object_id = indexes.object_id AND index_resumable_operations.index_id = indexes.index_id AND (index_resumable_operations.partition_number = partitions.partition_number OR index_resumable_operations.partition_number IS NULL)) THEN 1 ELSE 0 END' ELSE '0' END + ' AS ResumableIndexOperation' + + ', ' + CASE WHEN @Version >= 14 OR SERVERPROPERTY('EngineEdition') IN (5, 8) THEN 'CASE WHEN EXISTS(SELECT * FROM sys.index_resumable_operations index_resumable_operations WHERE state_desc = ''PAUSED'' AND index_resumable_operations.object_id = indexes.object_id AND index_resumable_operations.index_id = indexes.index_id' + CASE WHEN @PartitionLevel = 'Y' THEN ' AND (index_resumable_operations.partition_number = partitions.partition_number OR index_resumable_operations.partition_number IS NULL)' ELSE '' END + ') THEN 1 ELSE 0 END' ELSE '0' END + ' AS ResumableIndexOperation' + ', stats.stats_id AS StatisticsID' + ', stats.name AS StatisticsName' @@ -8378,11 +8467,13 @@ BEGIN + ', NULL AS IndexID, NULL AS IndexName' + ', NULL AS IndexType' + ', NULL AS AllowPageLocks' + + ', NULL AS HasFilter' + ', NULL AS IsImageText' + ', NULL AS IsNewLOB' + ', NULL AS IsFileStream' - + ', NULL AS IsColumnStore' + + ', NULL AS HasColumnstore' + ', NULL AS IsComputed' + + ', NULL AS IsClusteredIndexComputed' + ', NULL AS IsTimestamp' + ', NULL AS OnReadOnlyFileGroup' + ', NULL AS ResumableIndexOperation' @@ -8407,13 +8498,59 @@ BEGIN END SET @CurrentCommand = @CurrentCommand + ' WHERE objects.[type] IN(''U'',''V'')' + + CASE WHEN @Version >= 12 THEN ' AND (tables.is_memory_optimized = 0 OR tables.is_memory_optimized IS NULL)' ELSE '' END + CASE WHEN @MSShippedObjects = 'N' THEN ' AND objects.is_ms_shipped = 0' ELSE '' END + ' AND NOT EXISTS(SELECT * FROM sys.indexes indexes WHERE indexes.[object_id] = stats.[object_id] AND indexes.index_id = stats.stats_id)' + + ' AND NOT EXISTS(SELECT * FROM sys.indexes indexes2 WHERE indexes2.[object_id] = stats.[object_id] AND indexes2.type = 1 AND indexes2.is_disabled = 1)' + + IF @Version >= 12 + BEGIN + SET @CurrentCommand = @CurrentCommand + ' UNION ' + + SET @CurrentCommand = @CurrentCommand + 'SELECT schemas.[schema_id] AS SchemaID' + + ', schemas.[name] AS SchemaName' + + ', objects.[object_id] AS ObjectID' + + ', objects.[name] AS ObjectName' + + ', RTRIM(objects.[type]) AS ObjectType' + + ', tables.is_memory_optimized AS IsMemoryOptimized' + + ', NULL AS IndexID, NULL AS IndexName' + + ', NULL AS IndexType' + + ', NULL AS AllowPageLocks' + + ', NULL AS HasFilter' + + ', NULL AS IsImageText' + + ', NULL AS IsNewLOB' + + ', NULL AS IsFileStream' + + ', NULL AS HasColumnstore' + + ', NULL AS IsComputed' + + ', NULL AS IsClusteredIndexComputed' + + ', NULL AS IsTimestamp' + + ', NULL AS OnReadOnlyFileGroup' + + ', NULL AS ResumableIndexOperation' + + ', stats.stats_id AS StatisticsID' + + ', stats.name AS StatisticsName' + + ', stats.no_recompute AS NoRecompute' + + ', ' + CASE WHEN @Version >= 12 THEN 'stats.is_incremental' ELSE '0' END + ' AS IsIncremental' + + ', NULL AS PartitionID' + + ', NULL AS PartitionNumber' + + ', NULL AS PartitionCount' + + ', 0 AS [Order]' + + ', 0 AS Selected' + + ', 0 AS Completed' + + ' FROM sys.stats stats' + + ' INNER JOIN sys.objects objects ON stats.[object_id] = objects.[object_id]' + + ' INNER JOIN sys.schemas schemas ON objects.[schema_id] = schemas.[schema_id]' + + ' INNER JOIN sys.tables tables ON objects.[object_id] = tables.[object_id]' + + SET @CurrentCommand = @CurrentCommand + ' WHERE objects.[type] = ''U''' + + ' AND tables.is_memory_optimized = 1' + + CASE WHEN @MSShippedObjects = 'N' THEN ' AND objects.is_ms_shipped = 0' ELSE '' END + + ' AND NOT EXISTS(SELECT * FROM sys.indexes indexes WHERE indexes.[object_id] = stats.[object_id] AND indexes.index_id = stats.stats_id)' + END END SET @CurrentCommand = @CurrentCommand + ') IndexesStatistics' - INSERT INTO @tmpIndexesStatistics (SchemaID, SchemaName, ObjectID, ObjectName, ObjectType, IsMemoryOptimized, IndexID, IndexName, IndexType, AllowPageLocks, IsImageText, IsNewLOB, IsFileStream, IsColumnStore, IsComputed, IsTimestamp, OnReadOnlyFileGroup, ResumableIndexOperation, StatisticsID, StatisticsName, [NoRecompute], IsIncremental, PartitionID, PartitionNumber, PartitionCount, [Order], Selected, Completed) + INSERT INTO @tmpIndexesStatistics (SchemaID, SchemaName, ObjectID, ObjectName, ObjectType, IsMemoryOptimized, IndexID, IndexName, IndexType, AllowPageLocks, HasFilter, IsImageText, IsNewLOB, IsFileStream, HasColumnstore, IsComputed, IsClusteredIndexComputed, IsTimestamp, OnReadOnlyFileGroup, ResumableIndexOperation, StatisticsID, StatisticsName, [NoRecompute], IsIncremental, PartitionID, PartitionNumber, PartitionCount, [Order], Selected, Completed) EXECUTE @CurrentDatabase_sp_executesql @stmt = @CurrentCommand SET @Error = @@ERROR IF @Error <> 0 @@ -8513,11 +8650,13 @@ BEGIN @CurrentIndexName = IndexName, @CurrentIndexType = IndexType, @CurrentAllowPageLocks = AllowPageLocks, + @CurrentHasFilter = HasFilter, @CurrentIsImageText = IsImageText, @CurrentIsNewLOB = IsNewLOB, @CurrentIsFileStream = IsFileStream, - @CurrentIsColumnStore = IsColumnStore, + @CurrentHasColumnstore = HasColumnstore, @CurrentIsComputed = IsComputed, + @CurrentIsClusteredIndexComputed = IsClusteredIndexComputed, @CurrentIsTimestamp = IsTimestamp, @CurrentOnReadOnlyFileGroup = OnReadOnlyFileGroup, @CurrentResumableIndexOperation = ResumableIndexOperation, @@ -8655,6 +8794,7 @@ BEGIN AND @CurrentOnReadOnlyFileGroup = 0 AND EXISTS(SELECT * FROM @ActionsPreferred) AND (EXISTS(SELECT [Priority], [Action], COUNT(*) FROM @ActionsPreferred GROUP BY [Priority], [Action] HAVING COUNT(*) <> 3) OR @MinNumberOfPages > 0 OR @MaxNumberOfPages IS NOT NULL) + AND NOT (SERVERPROPERTY('EngineEdition') = 8 AND @CurrentDatabaseName IN ('master', 'model')) BEGIN SET @CurrentCommand = '' @@ -8693,25 +8833,33 @@ BEGIN -- Which actions are allowed? IF @CurrentIndexID IS NOT NULL AND EXISTS(SELECT * FROM @ActionsPreferred) BEGIN - IF @CurrentOnReadOnlyFileGroup = 0 AND @CurrentIndexType IN (1,2,3,4,5) AND (@CurrentIsMemoryOptimized = 0 OR @CurrentIsMemoryOptimized IS NULL) AND (@CurrentAllowPageLocks = 1 OR @CurrentIndexType = 5) + IF NOT (@CurrentOnReadOnlyFileGroup = 1) + AND NOT (@CurrentIsMemoryOptimized = 1) + AND NOT (@CurrentAllowPageLocks = 0) BEGIN INSERT INTO @CurrentActionsAllowed ([Action]) VALUES ('INDEX_REORGANIZE') END - IF @CurrentOnReadOnlyFileGroup = 0 AND @CurrentIndexType IN (1,2,3,4,5) AND (@CurrentIsMemoryOptimized = 0 OR @CurrentIsMemoryOptimized IS NULL) + IF NOT (@CurrentOnReadOnlyFileGroup = 1) + AND NOT (@CurrentIsMemoryOptimized = 1) BEGIN INSERT INTO @CurrentActionsAllowed ([Action]) VALUES ('INDEX_REBUILD_OFFLINE') END - IF @CurrentOnReadOnlyFileGroup = 0 - AND (@CurrentIsMemoryOptimized = 0 OR @CurrentIsMemoryOptimized IS NULL) - AND (@CurrentIsPartition = 0 OR @Version >= 12) - AND ((@CurrentIndexType = 1 AND @CurrentIsImageText = 0 AND @CurrentIsNewLOB = 0) - OR (@CurrentIndexType = 2 AND @CurrentIsNewLOB = 0) - OR (@CurrentIndexType = 1 AND @CurrentIsImageText = 0 AND @CurrentIsFileStream = 0 AND @Version >= 11) - OR (@CurrentIndexType = 2 AND @Version >= 11)) - AND (@CurrentIsColumnStore = 0 OR @Version < 11) - AND SERVERPROPERTY('EngineEdition') IN (3,5,8) + IF SERVERPROPERTY('EngineEdition') IN (3, 5, 8) + AND NOT (@CurrentOnReadOnlyFileGroup = 1) + AND NOT (@CurrentIsMemoryOptimized = 1) + AND NOT (@CurrentIsPartition = 1 AND @Version < 12) + AND NOT (@CurrentIndexType = 1 AND @CurrentIsImageText = 1) + AND NOT (@CurrentIndexType = 1 AND @CurrentIsFileStream = 1) + AND NOT (@CurrentIndexType = 1 AND @CurrentIsNewLOB = 1 AND @Version < 11) + AND NOT (@CurrentIndexType = 2 AND @CurrentIsNewLOB = 1 AND @Version < 11) + AND NOT (@CurrentIndexType = 3) + AND NOT (@CurrentIndexType = 4) + AND NOT (@CurrentIndexType = 5 AND @Version < 15) + AND NOT (@CurrentIndexType = 6 AND @Version < 15) + AND NOT (@CurrentIndexType = 1 AND @CurrentHasColumnstore = 1 AND @Version < 13) + AND NOT (@CurrentIndexType = 2 AND @CurrentHasColumnstore = 1 AND @Version < 13) BEGIN INSERT INTO @CurrentActionsAllowed ([Action]) VALUES ('INDEX_REBUILD_ONLINE') @@ -8799,9 +8947,11 @@ BEGIN SET @CurrentComment += 'ImageText: ' + CASE WHEN @CurrentIsImageText = 1 THEN 'Yes' WHEN @CurrentIsImageText = 0 THEN 'No' ELSE 'N/A' END + ', ' SET @CurrentComment += 'NewLOB: ' + CASE WHEN @CurrentIsNewLOB = 1 THEN 'Yes' WHEN @CurrentIsNewLOB = 0 THEN 'No' ELSE 'N/A' END + ', ' SET @CurrentComment += 'FileStream: ' + CASE WHEN @CurrentIsFileStream = 1 THEN 'Yes' WHEN @CurrentIsFileStream = 0 THEN 'No' ELSE 'N/A' END + ', ' - IF @Version >= 11 SET @CurrentComment += 'ColumnStore: ' + CASE WHEN @CurrentIsColumnStore = 1 THEN 'Yes' WHEN @CurrentIsColumnStore = 0 THEN 'No' ELSE 'N/A' END + ', ' + IF @Version >= 11 SET @CurrentComment += 'HasColumnStore: ' + CASE WHEN @CurrentHasColumnstore = 1 THEN 'Yes' WHEN @CurrentHasColumnstore = 0 THEN 'No' ELSE 'N/A' END + ', ' IF @Version >= 14 AND @Resumable = 'Y' SET @CurrentComment += 'Computed: ' + CASE WHEN @CurrentIsComputed = 1 THEN 'Yes' WHEN @CurrentIsComputed = 0 THEN 'No' ELSE 'N/A' END + ', ' + IF @Version >= 14 AND @Resumable = 'Y' AND @CurrentIndexType = 2 SET @CurrentComment += 'ClusteredIndexComputed: ' + CASE WHEN @CurrentIsClusteredIndexComputed = 1 THEN 'Yes' WHEN @CurrentIsClusteredIndexComputed = 0 THEN 'No' ELSE 'N/A' END + ', ' IF @Version >= 14 AND @Resumable = 'Y' SET @CurrentComment += 'Timestamp: ' + CASE WHEN @CurrentIsTimestamp = 1 THEN 'Yes' WHEN @CurrentIsTimestamp = 0 THEN 'No' ELSE 'N/A' END + ', ' + IF @Version >= 14 AND @Resumable = 'Y' SET @CurrentComment += 'HasFilter: ' + CASE WHEN @CurrentHasFilter = 1 THEN 'Yes' WHEN @CurrentHasFilter = 0 THEN 'No' ELSE 'N/A' END + ', ' SET @CurrentComment += 'AllowPageLocks: ' + CASE WHEN @CurrentAllowPageLocks = 1 THEN 'Yes' WHEN @CurrentAllowPageLocks = 0 THEN 'No' ELSE 'N/A' END + ', ' SET @CurrentComment += 'PageCount: ' + ISNULL(CAST(@CurrentPageCount AS nvarchar),'N/A') + ', ' SET @CurrentComment += 'Fragmentation: ' + ISNULL(CAST(@CurrentFragmentationLevel AS nvarchar),'N/A') @@ -8874,10 +9024,10 @@ BEGIN IF (@Version >= 14 OR SERVERPROPERTY('EngineEdition') IN (5,8)) AND @CurrentAction = 'INDEX_REBUILD_ONLINE' AND @CurrentResumableIndexOperation = 0 BEGIN INSERT INTO @CurrentAlterIndexWithClauseArguments (Argument) - SELECT CASE WHEN @Resumable = 'Y' AND @CurrentIndexType IN(1,2) AND @CurrentIsComputed = 0 AND @CurrentIsTimestamp = 0 THEN 'RESUMABLE = ON' ELSE 'RESUMABLE = OFF' END + SELECT CASE WHEN @Resumable = 'Y' AND @CurrentIndexType IN(1,2) AND @CurrentIsComputed = 0 AND @CurrentIsClusteredIndexComputed = 0 AND @CurrentIsTimestamp = 0 AND @CurrentHasFilter = 0 THEN 'RESUMABLE = ON' ELSE 'RESUMABLE = OFF' END END - IF (@Version >= 14 OR SERVERPROPERTY('EngineEdition') IN (5,8)) AND @CurrentAction = 'INDEX_REBUILD_ONLINE' AND @CurrentResumableIndexOperation = 0 AND @Resumable = 'Y' AND @CurrentIndexType IN(1,2) AND @CurrentIsComputed = 0 AND @CurrentIsTimestamp = 0 AND @TimeLimit IS NOT NULL + IF (@Version >= 14 OR SERVERPROPERTY('EngineEdition') IN (5,8)) AND @CurrentAction = 'INDEX_REBUILD_ONLINE' AND @Resumable = 'Y' AND @CurrentIndexType IN(1,2) AND @CurrentIsComputed = 0 AND @CurrentIsClusteredIndexComputed = 0 AND @CurrentIsTimestamp = 0 AND @CurrentHasFilter = 0 AND @TimeLimit IS NOT NULL BEGIN INSERT INTO @CurrentAlterIndexWithClauseArguments (Argument) SELECT 'MAX_DURATION = ' + CAST(DATEDIFF(MINUTE,SYSDATETIME(),DATEADD(SECOND,@TimeLimit,@StartTime)) AS nvarchar(max)) @@ -8989,16 +9139,16 @@ BEGIN SELECT 'SAMPLE ' + CAST(@CurrentStatisticsSample AS nvarchar) + ' PERCENT' END - IF @CurrentStatisticsResample = 'Y' + IF @CurrentNoRecompute = 1 BEGIN INSERT INTO @CurrentUpdateStatisticsWithClauseArguments (Argument) - SELECT 'RESAMPLE' + SELECT 'NORECOMPUTE' END - IF @CurrentNoRecompute = 1 + IF @CurrentStatisticsResample = 'Y' BEGIN INSERT INTO @CurrentUpdateStatisticsWithClauseArguments (Argument) - SELECT 'NORECOMPUTE' + SELECT 'RESAMPLE' END IF EXISTS (SELECT * FROM @CurrentUpdateStatisticsWithClauseArguments) @@ -9079,10 +9229,12 @@ BEGIN SET @CurrentIsImageText = NULL SET @CurrentIsNewLOB = NULL SET @CurrentIsFileStream = NULL - SET @CurrentIsColumnStore = NULL + SET @CurrentHasColumnstore = NULL SET @CurrentIsComputed = NULL + SET @CurrentIsClusteredIndexComputed = NULL SET @CurrentIsTimestamp = NULL SET @CurrentAllowPageLocks = NULL + SET @CurrentHasFilter = NULL SET @CurrentNoRecompute = NULL SET @CurrentIsIncremental = NULL SET @CurrentRowCount = NULL @@ -9150,7 +9302,6 @@ BEGIN SET @CurrentInStandby = NULL SET @CurrentRecoveryModel = NULL - SET @CurrentIsDatabaseAccessible = NULL SET @CurrentReplicaID = NULL SET @CurrentAvailabilityGroupID = NULL SET @CurrentAvailabilityGroup = NULL @@ -9185,8 +9336,8 @@ END GO IF (SELECT [Value] FROM #Config WHERE Name = 'CreateJobs') = 'Y' AND SERVERPROPERTY('EngineEdition') NOT IN(4, 5) - AND (IS_SRVROLEMEMBER('sysadmin') = 1 OR (DB_ID('rdsadmin') IS NOT NULL AND SUSER_SNAME(0x01) = 'rdsa')) - AND (SELECT [compatibility_level] FROM sys.databases WHERE database_id = DB_ID()) >= 90 + AND (IS_SRVROLEMEMBER('sysadmin') = 1 OR (EXISTS (SELECT * FROM sys.databases WHERE [name] = 'rdsadmin') AND SUSER_SNAME(0x01) = 'rdsa')) + AND (SELECT [compatibility_level] FROM sys.databases WHERE [name] = DB_NAME()) >= 90 AND NOT (EXISTS (SELECT * FROM #Config WHERE Name = 'BackupDirectory' AND [Value] IS NOT NULL) AND EXISTS (SELECT * FROM #Config WHERE Name = 'BackupURL' AND [Value] IS NOT NULL)) AND NOT (EXISTS (SELECT * FROM #Config WHERE Name = 'BackupURL' AND [Value] IS NOT NULL) AND EXISTS (SELECT * FROM #Config WHERE Name = 'CleanupTime' AND [Value] IS NOT NULL)) BEGIN @@ -9240,7 +9391,7 @@ BEGIN DECLARE @Version numeric(18,10) = CAST(LEFT(CAST(SERVERPROPERTY('ProductVersion') AS nvarchar(max)),CHARINDEX('.',CAST(SERVERPROPERTY('ProductVersion') AS nvarchar(max))) - 1) + '.' + REPLACE(RIGHT(CAST(SERVERPROPERTY('ProductVersion') AS nvarchar(max)), LEN(CAST(SERVERPROPERTY('ProductVersion') AS nvarchar(max))) - CHARINDEX('.',CAST(SERVERPROPERTY('ProductVersion') AS nvarchar(max)))),'.','') AS numeric(18,10)) - DECLARE @AmazonRDS bit = CASE WHEN DB_ID('rdsadmin') IS NOT NULL AND SUSER_SNAME(0x01) = 'rdsa' THEN 1 ELSE 0 END + DECLARE @AmazonRDS bit = CASE WHEN SERVERPROPERTY('EngineEdition') IN (5, 8) THEN 0 WHEN EXISTS (SELECT * FROM sys.databases WHERE [name] = 'rdsadmin') AND SUSER_SNAME(0x01) = 'rdsa' THEN 1 ELSE 0 END ---------------------------------------------------------------------------------------------------- --// Original Copyright 2024 Ola Hallengren. Licensed under the MIT License. //-- @@ -9347,28 +9498,28 @@ BEGIN INSERT INTO @Jobs ([Name], CommandTSQL, DatabaseName, OutputFileNamePart01, OutputFileNamePart02) SELECT 'DatabaseBackup - SYSTEM_DATABASES - FULL', - 'EXECUTE [dbo].[DatabaseBackup]' + CHAR(13) + CHAR(10) + '@Databases = ''SYSTEM_DATABASES'',' + CHAR(13) + CHAR(10) + CASE WHEN @BackupURL IS NOT NULL THEN '@URL = N''' + REPLACE(@BackupURL,'''','''''') + '''' ELSE '@Directory = ' + ISNULL('N''' + REPLACE(@BackupDirectory,'''','''''') + '''','NULL') END + ',' + CHAR(13) + CHAR(10) + '@BackupType = ''FULL'',' + CHAR(13) + CHAR(10) + '@Verify = ''Y'',' + CHAR(13) + CHAR(10) + '@CleanupTime = ' + ISNULL(CAST(@CleanupTime AS nvarchar),'NULL') + ',' + CHAR(13) + CHAR(10) + '@CheckSum = ''Y'',' + CHAR(13) + CHAR(10) + '@LogToTable = ''' + @LogToTable + '''', + 'EXECUTE [dbo].[DatabaseBackup]' + CHAR(13) + CHAR(10) + '@Databases = ''SYSTEM_DATABASES'',' + CHAR(13) + CHAR(10) + CASE WHEN @BackupURL IS NOT NULL THEN '@URL = N''' + REPLACE(@BackupURL,'''','''''') + '''' ELSE '@Directory = ' + ISNULL('N''' + REPLACE(@BackupDirectory,'''','''''') + '''','NULL') END + ',' + CHAR(13) + CHAR(10) + '@BackupType = ''FULL'',' + CHAR(13) + CHAR(10) + '@Verify = ''Y'',' + CHAR(13) + CHAR(10) + '@CleanupTime = ' + ISNULL(CAST(@CleanupTime AS nvarchar),'NULL') + ',' + CHAR(13) + CHAR(10) + '@Checksum = ''Y'',' + CHAR(13) + CHAR(10) + '@LogToTable = ''' + @LogToTable + '''', @DatabaseName, 'DatabaseBackup', 'FULL' INSERT INTO @Jobs ([Name], CommandTSQL, DatabaseName, OutputFileNamePart01, OutputFileNamePart02) SELECT 'DatabaseBackup - USER_DATABASES - DIFF', - 'EXECUTE [dbo].[DatabaseBackup]' + CHAR(13) + CHAR(10) + '@Databases = ''USER_DATABASES' + CASE WHEN @AmazonRDS = 1 THEN ', -rdsadmin%' ELSE '' END + ''',' + CHAR(13) + CHAR(10) + CASE WHEN @BackupURL IS NOT NULL THEN '@URL = N''' + REPLACE(@BackupURL,'''','''''') + '''' ELSE '@Directory = ' + ISNULL('N''' + REPLACE(@BackupDirectory,'''','''''') + '''','NULL') END + ',' + CHAR(13) + CHAR(10) + '@BackupType = ''DIFF'',' + CHAR(13) + CHAR(10) + '@Verify = ''Y'',' + CHAR(13) + CHAR(10) + '@CleanupTime = ' + ISNULL(CAST(@CleanupTime AS nvarchar),'NULL') + ',' + CHAR(13) + CHAR(10) + '@CheckSum = ''Y'',' + CHAR(13) + CHAR(10) + CASE WHEN @AmazonRDS = 1 THEN '@S3BucketArn = ' + ISNULL('N''' + REPLACE(@S3BucketArn,'''','''''') + '''','NULL') + ',' + CHAR(13) + CHAR(10) ELSE '' END + CASE WHEN @AmazonRDS = 1 THEN '@kms_master_key_arn = ' + ISNULL('N''' + REPLACE(@kms_master_key_arn,'''','''''') + '''','NULL') + ',' + CHAR(13) + CHAR(10) ELSE '' END + '@LogToTable = ''' + @LogToTable + '''', + 'EXECUTE [dbo].[DatabaseBackup]' + CHAR(13) + CHAR(10) + '@Databases = ''USER_DATABASES' + CASE WHEN @AmazonRDS = 1 THEN ', -rdsadmin%' ELSE '' END + ''',' + CHAR(13) + CHAR(10) + CASE WHEN @BackupURL IS NOT NULL THEN '@URL = N''' + REPLACE(@BackupURL,'''','''''') + '''' ELSE '@Directory = ' + ISNULL('N''' + REPLACE(@BackupDirectory,'''','''''') + '''','NULL') END + ',' + CHAR(13) + CHAR(10) + '@BackupType = ''DIFF'',' + CHAR(13) + CHAR(10) + '@Verify = ''Y'',' + CHAR(13) + CHAR(10) + '@CleanupTime = ' + ISNULL(CAST(@CleanupTime AS nvarchar),'NULL') + ',' + CHAR(13) + CHAR(10) + '@Checksum = ''Y'',' + CHAR(13) + CHAR(10) + CASE WHEN @AmazonRDS = 1 THEN '@S3BucketArn = ' + ISNULL('N''' + REPLACE(@S3BucketArn,'''','''''') + '''','NULL') + ',' + CHAR(13) + CHAR(10) ELSE '' END + CASE WHEN @AmazonRDS = 1 THEN '@kms_master_key_arn = ' + ISNULL('N''' + REPLACE(@kms_master_key_arn,'''','''''') + '''','NULL') + ',' + CHAR(13) + CHAR(10) ELSE '' END + '@LogToTable = ''' + @LogToTable + '''', @DatabaseName, 'DatabaseBackup', 'DIFF' INSERT INTO @Jobs ([Name], CommandTSQL, DatabaseName, OutputFileNamePart01, OutputFileNamePart02) SELECT 'DatabaseBackup - USER_DATABASES - FULL', - 'EXECUTE [dbo].[DatabaseBackup]' + CHAR(13) + CHAR(10) + '@Databases = ''USER_DATABASES' + CASE WHEN @AmazonRDS = 1 THEN ', -rdsadmin%' ELSE '' END + ''',' + CHAR(13) + CHAR(10) + CASE WHEN @BackupURL IS NOT NULL THEN '@URL = N''' + REPLACE(@BackupURL,'''','''''') + '''' ELSE '@Directory = ' + ISNULL('N''' + REPLACE(@BackupDirectory,'''','''''') + '''','NULL') END + ',' + CHAR(13) + CHAR(10) + '@BackupType = ''FULL'',' + CHAR(13) + CHAR(10) + '@Verify = ''Y'',' + CHAR(13) + CHAR(10) + '@CleanupTime = ' + ISNULL(CAST(@CleanupTime AS nvarchar),'NULL') + ',' + CHAR(13) + CHAR(10) + '@CheckSum = ''Y'',' + CHAR(13) + CHAR(10) + CASE WHEN @AmazonRDS = 1 THEN '@S3BucketArn = ' + ISNULL('N''' + REPLACE(@S3BucketArn,'''','''''') + '''','NULL') + ',' + CHAR(13) + CHAR(10) ELSE '' END + CASE WHEN @AmazonRDS = 1 THEN '@kms_master_key_arn = ' + ISNULL('N''' + REPLACE(@kms_master_key_arn,'''','''''') + '''','NULL') + ',' + CHAR(13) + CHAR(10) ELSE '' END + '@LogToTable = ''' + @LogToTable + '''', + 'EXECUTE [dbo].[DatabaseBackup]' + CHAR(13) + CHAR(10) + '@Databases = ''USER_DATABASES' + CASE WHEN @AmazonRDS = 1 THEN ', -rdsadmin%' ELSE '' END + ''',' + CHAR(13) + CHAR(10) + CASE WHEN @BackupURL IS NOT NULL THEN '@URL = N''' + REPLACE(@BackupURL,'''','''''') + '''' ELSE '@Directory = ' + ISNULL('N''' + REPLACE(@BackupDirectory,'''','''''') + '''','NULL') END + ',' + CHAR(13) + CHAR(10) + '@BackupType = ''FULL'',' + CHAR(13) + CHAR(10) + '@Verify = ''Y'',' + CHAR(13) + CHAR(10) + '@CleanupTime = ' + ISNULL(CAST(@CleanupTime AS nvarchar),'NULL') + ',' + CHAR(13) + CHAR(10) + '@Checksum = ''Y'',' + CHAR(13) + CHAR(10) + CASE WHEN @AmazonRDS = 1 THEN '@S3BucketArn = ' + ISNULL('N''' + REPLACE(@S3BucketArn,'''','''''') + '''','NULL') + ',' + CHAR(13) + CHAR(10) ELSE '' END + CASE WHEN @AmazonRDS = 1 THEN '@kms_master_key_arn = ' + ISNULL('N''' + REPLACE(@kms_master_key_arn,'''','''''') + '''','NULL') + ',' + CHAR(13) + CHAR(10) ELSE '' END + '@LogToTable = ''' + @LogToTable + '''', @DatabaseName, 'DatabaseBackup', 'FULL' INSERT INTO @Jobs ([Name], CommandTSQL, DatabaseName, OutputFileNamePart01, OutputFileNamePart02) SELECT 'DatabaseBackup - USER_DATABASES - LOG', - 'EXECUTE [dbo].[DatabaseBackup]' + CHAR(13) + CHAR(10) + '@Databases = ''USER_DATABASES' + CASE WHEN @AmazonRDS = 1 THEN ', -rdsadmin%' ELSE '' END + ''',' + CHAR(13) + CHAR(10) + CASE WHEN @BackupURL IS NOT NULL THEN '@URL = N''' + REPLACE(@BackupURL,'''','''''') + '''' ELSE '@Directory = ' + ISNULL('N''' + REPLACE(@BackupDirectory,'''','''''') + '''','NULL') END + ',' + CHAR(13) + CHAR(10) + '@BackupType = ''LOG'',' + CHAR(13) + CHAR(10) + '@Verify = ''Y'',' + CHAR(13) + CHAR(10) + '@CleanupTime = ' + ISNULL(CAST(@CleanupTime AS nvarchar),'NULL') + ',' + CHAR(13) + CHAR(10) + '@CheckSum = ''Y'',' + CHAR(13) + CHAR(10) + '@LogToTable = ''' + @LogToTable + '''', + 'EXECUTE [dbo].[DatabaseBackup]' + CHAR(13) + CHAR(10) + '@Databases = ''USER_DATABASES' + CASE WHEN @AmazonRDS = 1 THEN ', -rdsadmin%' ELSE '' END + ''',' + CHAR(13) + CHAR(10) + CASE WHEN @BackupURL IS NOT NULL THEN '@URL = N''' + REPLACE(@BackupURL,'''','''''') + '''' ELSE '@Directory = ' + ISNULL('N''' + REPLACE(@BackupDirectory,'''','''''') + '''','NULL') END + ',' + CHAR(13) + CHAR(10) + '@BackupType = ''LOG'',' + CHAR(13) + CHAR(10) + '@Verify = ''Y'',' + CHAR(13) + CHAR(10) + '@CleanupTime = ' + ISNULL(CAST(@CleanupTime AS nvarchar),'NULL') + ',' + CHAR(13) + CHAR(10) + '@Checksum = ''Y'',' + CHAR(13) + CHAR(10) + '@LogToTable = ''' + @LogToTable + '''', @DatabaseName, 'DatabaseBackup', 'LOG' @@ -9392,7 +9543,7 @@ BEGIN SELECT 'IndexOptimize - USER_DATABASES', 'EXECUTE [dbo].[IndexOptimize]' + CHAR(13) + CHAR(10) + '@Databases = ''USER_DATABASES' + CASE WHEN @AmazonRDS = 1 THEN ', -rdsadmin' ELSE '' END + ''',' + CHAR(13) + CHAR(10) + '@LogToTable = ''' + @LogToTable + '''', @DatabaseName, - 'IndexOptimize' + 'IndexOptimize' ---------------------------------------------------------------------------------------------------- INSERT INTO @Jobs ([Name], CommandTSQL, DatabaseName, OutputFileNamePart01) @@ -9626,4 +9777,30 @@ BEGIN @active_start_time=0, @active_end_time=235959 END - ---------------------------------------------------------------------------------------------------- \ No newline at end of file + +DECLARE @AmazonRDS bit = CASE WHEN DB_ID('rdsadmin') IS NOT NULL AND SUSER_SNAME(0x01) = 'rdsa' THEN 1 ELSE 0 END +DECLARE @job_id uniqueidentifier +DECLARE @step_id int +DECLARE @command nvarchar(max) + +IF @AmazonRDS = 0 + BEGIN + DECLARE JobCursor CURSOR FAST_FORWARD FOR SELECT job_id, step_id, command FROM msdb.dbo.sysjobsteps WHERE command LIKE '%DatabaseBackup%@CheckSum%' COLLATE SQL_Latin1_General_CP1_CS_AS + + OPEN JobCursor + FETCH JobCursor INTO @job_id, @step_id, @command + + WHILE @@FETCH_STATUS = 0 + BEGIN + SET @command = REPLACE(@command, '@CheckSum', '@Checksum') + + EXECUTE msdb.dbo.sp_update_jobstep @job_id = @job_id, @step_id = @step_id, @command = @command + + FETCH NEXT FROM JobCursor INTO @job_id, @step_id, @command + END + + CLOSE JobCursor + DEALLOCATE JobCursor + END + ---------------------------------------------------------------------------------------------------- +GO \ No newline at end of file