使用作业自动批量清理数据库日志文件

焰尾迭 的基础上修改

他的代码有一些缺陷,没法做到批量清理多个数据库日志,只能删除master日志,或者存储过程所在的数据库。

 可以把两个存储过程都建在master数据库,使用sa账户执行。

1.先建立清理日志存储过程(此处代码做了修改,正式使用时也注意结合自己的数据库服务器)

USE [master]
GO
/****** Object:  StoredProcedure [dbo].[usp_p_delDBLog]    Script Date: 02/14/2019 09:35:01 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROC [dbo].[usp_p_delDBLog](
    @DriveLimit AS BIGINT,
    @DBLogSise AS INT =0
)
/*
*    功能:收缩当前数据库日志文件
*    参数  @DriveLimit:当前数据库所在磁盘空间到达多少的时候进行收缩数据库  MB
*          @DBLogSise:日志文件收缩至多少M 默认收缩到最小
*/
AS 
BEGIN
    IF @DBLogSise<0 OR @DriveLimit<0
    BEGIN
        RETURN
    END
    
    --当前数据库所在磁盘
    DECLARE @Drive AS VARCHAR(10)
    DECLARE @Available AS BIGINT

    SELECT TOP 1  @Drive=SUBSTRING(filename,1,1)  from   sysfiles


    CREATE TABLE #TempFile(
        Drive VARCHAR(10),--磁盘
        Available BIGINT --可用大小MB
    )
    INSERT INTO #TempFile(Drive,Available)
    exec master..xp_fixeddrives

    --查询当前数据库所在磁盘剩余空间大小,
--此处查询的master所在的磁盘,(可能是C盘)
--可能跟使用的数据库不在一个盘符,传参数时注意@DriveLimit的值
SELECT @Available=Available FROM #TempFile WHERE Drive=@Drive --符合条件则进行收缩日志文件 IF @Available<=@DriveLimit BEGIN --查询出数据库对应的日志文件名称 DECLARE @strDBName AS NVARCHAR(500) DECLARE @strLogName AS NVARCHAR(500) DECLARE @strSQL AS VARCHAR(1000) --使用游标,批量清理类型为log的文件 declare B_Cursor cursor FOR SELECT B.name, A.name FROM master.sys.databases AS A INNER JOIN sys.master_files AS B ON A.database_id = B.database_id WHERE B.[type]=1 -- [type]=1为日志文件 open B_Cursor; fetch next from B_Cursor into @strLogName ,@strDBName while @@FETCH_STATUS =0 begin SET @strSQL=' use ['+@strDBName+']; -- 不适用use报错 --设置数据库恢复模式为简单 ALTER DATABASE ['+@strDBName+'] SET RECOVERY SIMPLE; --收缩日志文件 DBCC SHRINKFILE ('''+@strLogName+''' , '+CONVERT(VARCHAR(20),@DBLogSise)+'); --恢复数据库还原模式为完整 ALTER DATABASE ['+@strDBName+'] SET RECOVERY FULL ' --print @strDBName --print @strDBName --print @strSQL exec(@strSQL) fetch next from B_Cursor into @strLogName ,@strDBName end close B_Cursor; deallocate B_Cursor; END DROP TABLE #TempFile END

2.创建SQL作业的存储过程(创建作业代码没有修改)

USE [master]
GO
/****** Object:  StoredProcedure [dbo].[usp_p_CreateJob]    Script Date: 02/14/2019 11:36:13 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[usp_p_CreateJob](
    @jobname varchar(100),         
    @sql VARCHAR(MAX),                      
    @freqtype varchar(6)='day',     
    @fsinterval int=1,                
    @time int=235959,                     
    @description VARCHAR(1000)=''           
)
AS
/*
功能:创建SQL作业
参数:
    @jobname:作业名称
    @sql:要执行的命令
    @freqtype:时间周期,month 月,week 周,day 日
    @fsinterval:相对于每日的重复次数
    @time:开始执行时间,对于重复执行的作业,将从0点到23:59分
    @description:作业的描述
*/ 
BEGIN
    DECLARE @dbname AS VARCHAR(500)
    SET @dbname=DB_NAME()
        
    BEGIN TRANSACTION
    DECLARE @ReturnCode INT
    SELECT @ReturnCode = 0
    
    --添加类别
    IF NOT EXISTS (SELECT name FROM msdb.dbo.syscategories WHERE name='添加作业' AND category_class=1)
    BEGIN
        EXEC @ReturnCode = msdb.dbo.sp_add_category @class=N'JOB', @type=N'LOCAL', @name=N'添加作业'
        IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
    END
    
    --删除作业  
    DECLARE @JobID BINARY(16)   
    DECLARE @ErrMsg NVARCHAR(500)      
    SELECT  @JobID = job_id  FROM msdb.dbo.sysjobs WHERE name = @JobName  
    IF ( @JobID IS NOT NULL )  
    BEGIN   
      -- 检查此作业是否为多重服务器作业  
      IF ( EXISTS ( SELECT * FROM msdb.dbo.sysjobservers WHERE ( job_id = @JobID ) AND ( server_id <> 0 ) ) )  
      BEGIN  
        --多重服务器作业不操作  
        SET @ErrMsg = '无法导入作业"' + @JobName + '",因为已经有相同名称的多重服务器作业。'  
        RAISERROR (@ErrMsg, 16, 1)   
        GOTO QuitWithRollback  
      END  
      ELSE  
       BEGIN  
        -- 删除[本地]作业   
        EXECUTE msdb.dbo.sp_delete_job @job_name = @JobName  
        SELECT @JobID = NULL  
       END  
     END  

    SET @JobID = NULL    
    EXEC @ReturnCode =  msdb.dbo.sp_add_job @job_name=@jobname, 
            @enabled=1, 
            @notify_level_eventlog=2, 
            @notify_level_email=0, 
            @notify_level_netsend=0, 
            @notify_level_page=0, 
            @delete_level=0, 
            @description=@description, 
            @category_name=N'添加作业', 
            @owner_login_name=N'sa', @job_id = @jobId OUTPUT
    IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
    /****** Object:  Step [数据同步]    Script Date: 01/25/2014 23:00:36 ******/
    EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @job_id=@jobId, @step_name=@jobname, 
            @step_id=1, 
            @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=5, 
            @os_run_priority=0, @subsystem=N'TSQL', 
            @command= @sql, 
            @database_name=@dbname, 
            @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
    
    --创建调度
    declare @ftype int,@fstype int,@ffactor int
    select @ftype=case @freqtype when 'day' then 4
                                            when 'week' then 8
                                            when 'month' then 16 end
            ,@fstype=case @fsinterval when 1 then 0 else 8 end
    if @fsinterval<>1 set @time=0
    set @ffactor=case @freqtype when 'day' then 0 else 1 end
    
    EXEC msdb..sp_add_jobschedule @job_name=@jobname, 
        @name = @jobname,
        @freq_type=@ftype ,                                        
        @freq_interval=1,                                       
        @freq_subday_type=@fstype,                       
        @freq_subday_interval=@fsinterval,        
        @freq_recurrence_factor=@ffactor,
        @active_start_time=@time                         
        
    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:
END

3.在SQL中执行作业添加

--添加作业
--作业每天间隔两小时执行一次
--执行条件为磁盘空间不足 50000MB,即@DriveLimit=50000 可自行配置
DECLARE @@jobname AS VARCHAR(1000)
SELECT @@jobname=DB_NAME()+'_自动清理当前数据库日志文件'
EXEC dbo.usp_p_CreateJob @jobname = @@jobname, -- varchar(100)
    @sql = 'EXEC usp_p_delDBLog @DriveLimit=50000,@DBLogSise=0', -- varchar(max)
    @freqtype = 'day', -- varchar(6)
    @fsinterval = 2, -- int
    @time = 235959, -- int
    @description = '自动清理当前数据库日志文件' -- varchar(1000)

 

posted @ 2019-02-14 11:57  AlexLeeLi  阅读(404)  评论(0编辑  收藏  举报