Hi,
Since upgrading to SQL 2017 (from 2017), the SSIS maintenance job keeps failing. The job step is the following..
DECLARE @role int SET @role =(SELECT [role] FROM [sys].[dm_hadr_availability_replica_states] hars INNER JOIN [sys].[availability_databases_cluster] adc ON hars.[group_id] = adc.[group_id] WHERE hars.[is_local] = 1 AND adc.[database_name] ='SSISDB') IF DB_ID('SSISDB') IS NOT NULL AND(@role IS NULL OR @role = 1) EXEC [SSISDB].[internal].[cleanup_server_retention_window]
However it fails with the error message"A cursor with the name 'execution_cursor' does not exist."
After looking through the proc, it de-allocated the cursor then tries to access it again within the while loop. So we are deleting 1000 records from the SSIS history at a time, but then hit the error. Whilst I could modify the procedure, I thought
i'd see if anyone else encounted this.
SET QUOTED_IDENTIFIER ON SET ANSI_NULLS ON GO CREATE PROCEDURE [internal].[cleanup_server_retention_window] WITH EXECUTE AS 'AllSchemaOwner' AS SET NOCOUNT ON DECLARE @enable_clean_operation bit DECLARE @retention_window_length int DECLARE @server_operation_encryption_level int DECLARE @caller_name nvarchar(256) DECLARE @caller_sid varbinary(85) DECLARE @operation_id bigint EXECUTE AS CALLER SET @caller_name = SUSER_NAME() SET @caller_sid = SUSER_SID() REVERT BEGIN TRY SELECT @enable_clean_operation = CONVERT(bit, property_value) FROM [catalog].[catalog_properties] WHERE property_name = 'OPERATION_CLEANUP_ENABLED' IF @enable_clean_operation = 1 BEGIN SELECT @retention_window_length = CONVERT(int,property_value) FROM [catalog].[catalog_properties] WHERE property_name = 'RETENTION_WINDOW' IF @retention_window_length <= 0 BEGIN RAISERROR(27163 ,16,1,'RETENTION_WINDOW') END SELECT @server_operation_encryption_level = CONVERT(int,property_value) FROM [catalog].[catalog_properties] WHERE property_name = 'SERVER_OPERATION_ENCRYPTION_LEVEL' IF @server_operation_encryption_level NOT in (1, 2) BEGIN RAISERROR(27163 ,16,1,'SERVER_OPERATION_ENCRYPTION_LEVEL') END INSERT INTO [internal].[operations] ( [operation_type], [created_time], [object_type], [object_id], [object_name], [status], [start_time], [caller_sid], [caller_name] ) VALUES ( 2, SYSDATETIMEOFFSET(), NULL, NULL, NULL, 1, SYSDATETIMEOFFSET(), @caller_sid, @caller_name ) SET @operation_id = SCOPE_IDENTITY() DECLARE @temp_date datetimeoffset DECLARE @rows_affected bigint DECLARE @delete_batch_size int SET @delete_batch_size = 1000 SET @rows_affected = @delete_batch_size SET @temp_date = DATEADD(day, -@retention_window_length, SYSDATETIMEOFFSET()) CREATE TABLE #deleted_ops (operation_id bigint, operation_type smallint) DECLARE execution_cursor CURSOR GLOBAL FOR SELECT operation_id FROM #deleted_ops WHERE operation_type = 200 DECLARE @sqlString_operation_messages_scaleout nvarchar(1024) DECLARE @sqlString_event_messages_scaleout nvarchar(1024) DECLARE @sqlString_event_message_context_scaleout nvarchar(1024) IF @server_operation_encryption_level = 1 BEGIN DECLARE @execution_id bigint DECLARE @sqlString nvarchar(1024) DECLARE @sqlString_cert nvarchar(1024) DECLARE @key_name [internal].[adt_name] DECLARE @certificate_name [internal].[adt_name] WHILE (@rows_affected = @delete_batch_size) BEGIN DELETE TOP (@delete_batch_size) FROM [internal].[operations] OUTPUT DELETED.operation_id, DELETED.operation_type INTO #deleted_ops WHERE ( [end_time] <= @temp_date OR ([end_time] IS NULL AND [status] = 1 AND [created_time] <= @temp_date )) SET @rows_affected = @@ROWCOUNT OPEN execution_cursor FETCH NEXT FROM execution_cursor INTO @execution_id WHILE @@FETCH_STATUS = 0 BEGIN SET @key_name = 'MS_Enckey_Exec_'+CONVERT(varchar,@execution_id) SET @certificate_name = 'MS_Cert_Exec_'+CONVERT(varchar,@execution_id) SET @sqlString_operation_messages_scaleout = 'delete from [internal].[operation_messages_scaleout] where operation_id = '+CONVERT(varchar,@execution_id) SET @sqlString_event_messages_scaleout = 'delete from [internal].[event_messages_scaleout] where operation_id = '+CONVERT(varchar,@execution_id) SET @sqlString_event_message_context_scaleout = 'delete from [internal].[event_message_context_scaleout] where operation_id = '+CONVERT(varchar,@execution_id) SET @sqlString = 'DROP SYMMETRIC KEY '+ @key_name SET @sqlString_cert = 'DROP CERTIFICATE '+ @certificate_name BEGIN TRY EXECUTE sp_executesql @sqlString EXECUTE sp_executesql @sqlString_cert EXECUTE sp_executesql @sqlString_operation_messages_scaleout EXECUTE sp_executesql @sqlString_event_messages_scaleout EXECUTE sp_executesql @sqlString_event_message_context_scaleout END TRY BEGIN CATCH END CATCH FETCH NEXT FROM execution_cursor INTO @execution_id END CLOSE execution_cursor TRUNCATE TABLE #deleted_ops END DROP TABLE #deleted_ops DEALLOCATE execution_cursor END ELSE BEGIN WHILE (@rows_affected = @delete_batch_size) BEGIN DELETE TOP (@delete_batch_size) FROM [internal].[operations] OUTPUT DELETED.operation_id, DELETED.operation_type INTO #deleted_ops WHERE ( [end_time] <= @temp_date OR ([end_time] IS NULL AND [status] = 1 AND [created_time] <= @temp_date )) SET @rows_affected = @@ROWCOUNT OPEN execution_cursor FETCH NEXT FROM execution_cursor INTO @execution_id WHILE @@FETCH_STATUS = 0 BEGIN SET @sqlString_operation_messages_scaleout = 'delete from [internal].[operation_messages_scaleout] where operation_id = '+CONVERT(varchar,@execution_id) SET @sqlString_event_messages_scaleout = 'delete from [internal].[event_messages_scaleout] where operation_id = '+CONVERT(varchar,@execution_id) SET @sqlString_event_message_context_scaleout = 'delete from [internal].[event_message_context_scaleout] where operation_id = '+CONVERT(varchar,@execution_id) BEGIN TRY EXECUTE sp_executesql @sqlString_operation_messages_scaleout EXECUTE sp_executesql @sqlString_event_messages_scaleout EXECUTE sp_executesql @sqlString_event_message_context_scaleout END TRY BEGIN CATCH END CATCH FETCH NEXT FROM execution_cursor INTO @execution_id END CLOSE execution_cursor TRUNCATE TABLE #deleted_ops DEALLOCATE execution_cursor END DROP TABLE #deleted_ops END UPDATE [internal].[operations] SET [status] = 7, [end_time] = SYSDATETIMEOFFSET() WHERE [operation_id] = @operation_id END END TRY BEGIN CATCH IF @server_operation_encryption_level = 1 BEGIN IF (CURSOR_STATUS('local', 'execution_cursor') = 1 OR CURSOR_STATUS('local', 'execution_cursor') = 0) BEGIN CLOSE execution_cursor DEALLOCATE execution_cursor END END UPDATE [internal].[operations] SET [status] = 4, [end_time] = SYSDATETIMEOFFSET() WHERE [operation_id] = @operation_id; THROW END CATCH RETURN 0 GO