zoukankan      html  css  js  c++  java
  • SQL Server 重复执行作业中某个步骤

    一、说明

    在SQL Server 的作业中,有些时候我们希望步骤在执行失败后可以重复执行多几次,而我产生这个念头的是因为我在执行某个步骤(这个步骤对分区表进行修改分区方案、分区函数)的时候出现死锁了,如下面描述:

    消息1205,级别13,状态55,第1 行

    事务(进程ID 115)与另一个进程被死锁在锁资源上,并且已被选作死锁牺牲品。请重新运行该事务。

    我想到解决这个问题的方法是重复执行多几次这个步骤(经测试执行几次可行),所以这里就讲讲如果让数据库作业完成这一动作。

    二、测试实验

    (一) 测试方案:

    我们在作业中设置了简单的两个步骤,步骤1往表中插入一条数据,步骤2更新这条记录,让计数器+1,这就测试了成功时候,说明重复次数是没用的;对步骤2进行修改,让步骤2抛出一个异常,因为我们需要对表进行计数器+1,所以我们这里就抛出一个异常,扑捉到这个异常,进行计数器+1后,再把这个异常抛出去,抛第一个异常是模拟执行失败的,抛第二个异常就是让作业在失败情况下重复执行,因为使用TRY和CATCH后第一个异常就给捕获了。

    (二) 创建表:

    CREATE TABLE [dbo].[TestJobCounts](
        [Id] [int] IDENTITY(1,1) NOT NULL,
        [Counts] [int] NULL,
        [UpdateTime] [datetime] NULL,
     CONSTRAINT [PK_TestJobCounts] PRIMARY KEY CLUSTERED
    (
        [Id] ASC
    )WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
    ) ON [PRIMARY]

    (三) 创建步骤1需要执行的存储过程:

    -- =============================================
    -- Author:        <Viajar>
    -- Create date: <2011.09.14>
    -- Description:    <插入数据>
    -- =============================================
    CREATE PROCEDURE [dbo].[sp_Insert] 
    AS
    BEGIN
        INSERT INTO [TestBackupDB].[dbo].[TestJobCounts]
                   ([Counts]
                   ,[UpdateTime])
             VALUES
                   (0
                   ,getdate())
    END

    (四) 创建步骤2需要执行的存储过程:

    -- =============================================
    -- Author:        <Viajar>
    -- Create date: <2011.09.14>
    -- Description:    <更新数据>
    -- =============================================
    CREATE PROCEDURE [dbo].[sp_UpdateCount] 
    AS
    BEGIN
        BEGIN TRANSACTION AltPS
            BEGIN TRY
                UPDATE [TestBackupDB].[dbo].[TestJobCounts]
                   SET [Counts] = [Counts]+1
                RAISERROR (N'This is message %s %d.', -- Message text.
                   13, -- Severity,
                   55, -- State,
                   N'number', -- First argument.
                   5); -- Second argument.
            END TRY
    
            BEGIN CATCH
              IF @@TRANCOUNT > 0
                PRINT 'Being ROLLBACK'
                ROLLBACK TRANSACTION AltPS--回滚
                UPDATE [TestBackupDB].[dbo].[TestJobCounts]
                   SET [Counts] = [Counts]+1
                 WHERE Id = (select max(id) from [TestJobCounts])
                PRINT '失败'
                RAISERROR (N'This is message %s %d.', -- Message text.
                   13, -- Severity,
                   55, -- State,
                   N'number', -- First argument.
                   5); -- Second argument.
            END CATCH
    
            IF @@TRANCOUNT > 0
            BEGIN
                PRINT 'Being COMMIT'
                COMMIT TRANSACTION AltPS;--执行
                PRINT '成功'
            END
    END

     

    (五) 创建作业:

    USE [msdb]
    GO
    /****** 对象:  Job [测试作业执行次数]    脚本日期: 09/14/2011 11:36:51 ******/
    BEGIN TRANSACTION
    DECLARE @ReturnCode INT
    SELECT @ReturnCode = 0
    /****** 对象:  JobCategory [[Uncategorized (Local)]]]    脚本日期: 09/14/2011 11:36:51 ******/
    IF NOT EXISTS (SELECT name FROM msdb.dbo.syscategories WHERE name=N'[Uncategorized (Local)]' AND category_class=1)
    BEGIN
    EXEC @ReturnCode = msdb.dbo.sp_add_category @class=N'JOB', @type=N'LOCAL', @name=N'[Uncategorized (Local)]'
    IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
    
    END
    
    DECLARE @jobId BINARY(16)
    EXEC @ReturnCode =  msdb.dbo.sp_add_job @job_name=N'测试作业执行次数', 
            @enabled=1, 
            @notify_level_eventlog=0, 
            @notify_level_email=0, 
            @notify_level_netsend=0, 
            @notify_level_page=0, 
            @delete_level=0, 
            @description=N'无描述。', 
            @category_name=N'[Uncategorized (Local)]', 
            @owner_login_name=N'sa', @job_id = @jobId OUTPUT
    IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
    /****** 对象:  Step [插入一条数据]    脚本日期: 09/14/2011 11:36:52 ******/
    EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @job_id=@jobId, @step_name=N'插入一条数据', 
            @step_id=1, 
            @cmdexec_success_code=0, 
            @on_success_action=3, 
            @on_success_step_id=0, 
            @on_fail_action=2, 
            @on_fail_step_id=0, 
            @retry_attempts=0, 
            @retry_interval=0, 
            @os_run_priority=0, @subsystem=N'TSQL', 
            @command=N'exec dbo.sp_Insert', 
            @database_name=N'TestBackupDB', 
            @flags=0
    IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
    /****** 对象:  Step [执行多次存储过程]    脚本日期: 09/14/2011 11:36:52 ******/
    EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @job_id=@jobId, @step_name=N'执行多次存储过程', 
            @step_id=2, 
            @cmdexec_success_code=0, 
            @on_success_action=1, 
            @on_success_step_id=0, 
            @on_fail_action=2, 
            @on_fail_step_id=0, 
            @retry_attempts=5, 
            @retry_interval=1, 
            @os_run_priority=0, @subsystem=N'TSQL', 
            @command=N'exec dbo.sp_UpdateCount', 
            @database_name=N'TestBackupDB', 
            @flags=0
    IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
    EXEC @ReturnCode = msdb.dbo.sp_update_job @job_id = @jobId, @start_step_id = 1
    IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
    EXEC @ReturnCode = msdb.dbo.sp_add_jobschedule @job_id=@jobId, @name=N'执行时间', 
            @enabled=1, 
            @freq_type=4, 
            @freq_interval=1, 
            @freq_subday_type=4, 
            @freq_subday_interval=10, 
            @freq_relative_interval=0, 
            @freq_recurrence_factor=0, 
            @active_start_date=20110914, 
            @active_end_date=99991231, 
            @active_start_time=0, 
            @active_end_time=235959
    IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
    EXEC @ReturnCode = msdb.dbo.sp_add_jobserver @job_id = @jobId, @server_name = N'(local)'
    IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
    COMMIT TRANSACTION
    GOTO EndSave
    QuitWithRollback:
        IF (@@TRANCOUNT > 0) ROLLBACK TRANSACTION
    EndSave:

    附图一:设置步骤之间的关系:


    (图1)

    附图二:设置步骤2失败时重试的次数以及每次重试的时间间隔,这里需要注意的是:1,如果步骤2执行成功,是不会执行重试的,直接就退出报告成功的作业了;2,这里重试次数设置为5,那么一共执行的次数就会是6次,因为要加上本身执行那一次;


    (图2)

    三、测试效果

    (一) 执行中,注意状态中的重试间隔:


    (图3)

    (二) 执行完,这是重复执行了5次依然失败的效果图:


    (图4)

    (三) 查看表,发现Counts的数值是6,说明本身执行1次,外加重试执行5次:


    (图5)

    四、参考文献

    如何设置作业步骤的成功流或失败流 (SQL Server Management Studio)

  • 相关阅读:
    socket
    netstat
    列表
    突然发现不会写代码了
    算法资源
    bit位操作
    排序算法
    连续子数组最大和
    books
    凸优化
  • 原文地址:https://www.cnblogs.com/gaizai/p/2176198.html
Copyright © 2011-2022 走看看