zoukankan      html  css  js  c++  java
  • 【sql server自动化】sql server自动化备份

    【1】备份SP

        
    use master
    go
    
        
    if object_id('Generalization_Backup') is not null
    drop procedure Generalization_Backup;
    go
        
    set ANSI_NULLS ON
    set QUOTED_IDENTIFIER ON
    go
    
        
    create PROCEDURE [dbo].[Generalization_Backup]
        @Database_Name NVARCHAR(50),        --输入_备份数据库名称
        @Bakup_Type varchar(200),           --输入_备份类型:full完整,diff差异备份,tran事务日志
        @Bakup_PATH_DIR NVARCHAR(200),        --输入_备份文件夹URL
        @Out_Message NVARCHAR(400) OUT      --输出_输出消息
    as
    begin
        DECLARE @Bakup_Dir NVARCHAR(200),  --备份路径上级目录
                @SQL NVARCHAR(MAX),         --动态语句
                @Day NCHAR(8),              --备份时间(年月日)
                @Date NCHAR(11),            --备份时间(年月日_小时)
                @Path NVARCHAR(200),        --备份路径
                @Bakup_name NVARCHAR(100),   --备份文件名
                @Bakup_Folder NVARCHAR(200), --备份文件夹名
                @bakup_URL nvarchar(1000)
                
    
    --判断数据库名是否正确    
        IF NOT EXISTS(SELECT TOP 1 NULL FROM master.sys.databases WHERE NAME=@Database_Name)
        BEGIN
                SET @Out_Message='未找到名为'+@Database_Name+'的数据库,请检查输入数据库名'
                RAISERROR (@Out_Message,16,1)
                RETURN -1
        END
    
    --创建备份文件夹    
        EXEC MASTER.dbo.xp_create_subdir @Bakup_PATH_DIR
    
    --验证备份文件夹是否创建成功
        declare @create_dir_info table (folder varchar(500),tree_high int)
    
        SELECT @Bakup_Dir=LEFT(@Bakup_PATH_DIR,LEN(@Bakup_PATH_DIR)-charindex('',REVERSE(@Bakup_PATH_DIR),2)+1)
        select @Bakup_Folder=SUBSTRING( @Bakup_PATH_DIR,LEN(@Bakup_PATH_DIR)-charindex('',REVERSE(@Bakup_PATH_DIR),2)+2,charindex('',REVERSE(@Bakup_PATH_DIR),2)-2)
        insert into @create_dir_info exec master.dbo.xp_dirtree @Bakup_Dir,1,0
        
        if not exists(select 1 from @create_dir_info where folder = @Bakup_Folder)
        begin
             SET @Out_Message='新建备份文件夹'+@Bakup_PATH_DIR+' 失败!'
             RAISERROR (@Out_Message,16,1)
             RETURN -1
        end
        
    --全备
        declare @disk varchar(100),@dbsize_GB decimal(18,3),@disk_freeSize_GB decimal(18,3)
        declare @disk_info table (drive varchar(100),size_MB int)
    --获取磁盘分区及对应大小    
        insert into @disk_info
        exec master.dbo.xp_fixeddrives
    --获取我们要备份的数据库现在有多大
        select @dbsize_GB=cast(sum(t1.size*8.0/1024/1024) as decimal(18,3))
        from master.sys.master_files t1
        join master.sys.databases t2 on t1.database_id=t2.database_id
        where t2.name=@Database_Name
    
    --判断当前磁盘空间是否充足,阀值为被备份的数据库+20G
        select @disk=left(@Bakup_PATH_DIR,1)
        select @disk_freeSize_GB=cast(size_MB/1024.0 as decimal(18,3)) from @disk_info where drive=@disk
        if @disk_freeSize_GB<@dbsize_GB+20
        begin
            SET @Out_Message='备份路径:'+@Bakup_PATH_DIR+' 磁盘空间不足(少于备份数据库大小+20G)!'
             RAISERROR (@Out_Message,16,1)
             RETURN -1
        end
        
        declare @create_sondir varchar(1000)
    
        if @Bakup_Type='full'
        begin
            --创建备份子文件夹    
            
            set @create_sondir=@Bakup_PATH_DIR+@Database_Name+''
            EXEC MASTER.dbo.xp_create_subdir @create_sondir
                begin try
                    select @Bakup_name=@database_name+'_'+@bakup_type+'_'+convert(char(8),getdate(),112)
                    set @bakup_URL=@Bakup_PATH_DIR+@Database_Name+''+@Bakup_name+'.bak'
                    set @sql='backup database '+@database_name+' to disk='''+@bakup_URL+''' with init'
                    exec(@sql)
                    
                end try
                
                BEGIN CATCH
                    SET @Out_Message='系统输出了错误信息,错误信息为:'+ERROR_MESSAGE()+';错误号为:'+CAST(ERROR_NUMBER() AS NVARCHAR(10))+',执行失败!'
                    RAISERROR (@Out_Message,16,1)
                    RETURN -1
                END CATCH
                
        end
        
        if @Bakup_Type='diff'
        begin
            --创建备份子文件夹    
            set @create_sondir=@Bakup_PATH_DIR+@Database_Name+''
            EXEC MASTER.dbo.xp_create_subdir @create_sondir
                begin try
                    select @Bakup_name=@database_name+'_'+@bakup_type+'_'+convert(char(8),getdate(),112)+'_'+cast(datepart(hour,getdate()) as varchar)
                    set @bakup_URL=@Bakup_PATH_DIR+@Database_Name+''+@Bakup_name+'.bak'
                    set @sql='backup database '+@database_name+' to disk='''+@bakup_URL+''' with init,differential'
                    exec(@sql)
                    
                end try
                
                BEGIN CATCH
                    SET @Out_Message='系统输出了错误信息,错误信息为:'+ERROR_MESSAGE()+';错误号为:'+CAST(ERROR_NUMBER() AS NVARCHAR(10))+',执行失败!'
                    RAISERROR (@Out_Message,16,1)
                    RETURN -1
                END CATCH
                
        end
        
        if @Bakup_Type='tran'
        begin
            --创建备份子文件夹    
            set @create_sondir=@Bakup_PATH_DIR+@Database_Name+''
            EXEC MASTER.dbo.xp_create_subdir @create_sondir
                begin try
                    select @Bakup_name=@database_name+'_'+@bakup_type+'_'+convert(char(8),getdate(),112)+'_'+replace(CONVERT(varchar(100), GETDATE(), 24),':','')
                    set @bakup_URL=@Bakup_PATH_DIR+@Database_Name+''+@Bakup_name+'.trn'
                    set @sql='backup log '+@database_name+' to disk='''+@bakup_URL+''' with init'
                    exec(@sql)
                    
                end try
                
                BEGIN CATCH
                    SET @Out_Message='系统输出了错误信息,错误信息为:'+ERROR_MESSAGE()+';错误号为:'+CAST(ERROR_NUMBER() AS NVARCHAR(10))+',执行失败!'
                    RAISERROR (@Out_Message,16,1)
                    RETURN -1
                END CATCH
                
        end
        set @Out_Message='OK'
    
    end

    【2】全备代码

    /*
        需求:如果数据库小的,就每天备份一次,数据库大的就每周做一次全备,大小阀值为10G
    */
    use master
    go
    --select * from master..small_db
    --select * from master..big_db
    --select * from master..backup_info
    --select * from master..tran_db
    --select * from master..diff_db
    
    set nocount on
    go
    --【1】构造临时存放表
    --构造小数据库 small_db
        if object_id('small_db') is not null
        begin
            drop table small_db
        end
    
            
        ;with temp1 as (
            select t2.name,sum(t1.size*8.0/1024/1024) as size_GB,case when isnumeric(right(t2.name,6) )=0 then t2.name+'_300000' else t2.name end as temp_name
            from master.sys.master_files t1
            join master.sys.databases t2 on t1.database_id=t2.database_id
            where  t2.name not in ('tempdb','model')
            group by t2.name
        )
        ,temp2 as 
        (
            select *,  row_number() over(partition by left(t2.temp_name,len(t2.temp_name)-7) order by cast(right(t2.temp_name,6) as int) desc)  as rn
            from temp1 t2
            
        )
        select t2.name,t2.size_GB,row_number() over(order by t2.size_GB) as rn,0 as flag
        into master..small_db
        from temp2 t2 
        where rn=1 
        and size_GB<=10 --区分大数据库与小数据库的阀值,单位GB
    
    --构造大数据库 big_db
        if object_id('big_db') is not null
        begin
            drop table big_db;
        end
    
            ;with temp1 as (
            select t2.name,sum(t1.size*8.0/1024/1024) as size_GB,case when isnumeric(right(t2.name,6) )=0 then t2.name+'_300000' else t2.name end as temp_name
            from master.sys.master_files t1
            join master.sys.databases t2 on t1.database_id=t2.database_id
            where  t2.name not in ('tempdb','model')
            group by t2.name
            )
            ,temp2 as 
            (
                select *,  row_number() over(partition by left(t2.temp_name,len(t2.temp_name)-7) order by cast(right(t2.temp_name,6) as int) desc)  as rn
                from temp1 t2
                
            )
            select t2.name,t2.size_GB,row_number() over(order by t2.size_GB) as rn,0 as flag
            into master..big_db
            from temp2 t2 
            where rn=1 
            and size_GB>10 --区分大数据库与小数据库的阀值,单位GB
        
    
    -- 构造日志记录表 backup_info
        if object_id('backup_info') is  null
        create table backup_info(
            db_name varchar(100),
            recovery_date varchar(20),
            operate varchar(50),
            msg varchar(4000),
            flag  as case when msg='OK' then 1 else 0 end
        )
    
    
    --【2】delcare 定义相关变量 与 初始化
    use master
    go
        declare @bak_path varchar(300),@db_name varchar(300),@operate_type varchar(50)
        declare @rn int,@rn_count int
        declare @flag int
        declare @msg varchar(4000)
        
      --指定备份目录
    set @bak_path='d:DB_AUTO_BAK' --【3】小数据库 备份 set @rn=1 select @rn_count=count(1) from master..small_db while @rn<=@rn_count begin set @operate_type='full' select @db_name=name,@flag=flag from master..small_db where rn = @rn begin try if @flag=0 begin exec master..[Generalization_Backup] @Database_Name=@db_name, @Bakup_Type=@operate_type, @Bakup_PATH_DIR=@bak_path, @Out_Message= @msg output if @msg='OK' update master..small_db set flag=1 where rn=@rn end end try begin catch if @msg='ok' set @msg='operate fail!' insert into backup_info(db_name,recovery_date,operate,msg) values(@db_name,convert(char(10),getdate(),120),@operate_type,@msg); end catch set @rn=@rn+1 end --【4】大数据库 备份 set @rn=1 select @rn_count=count(1) from master..big_db while @rn<=@rn_count begin select @db_name=name,@flag=flag from master..big_db where rn = @rn set @operate_type='full' if exists( select 1 from msdb..backupset where type='D' and datediff(day,backup_start_date,getdate())<=7 and database_name=@db_name) and @db_name!='master' begin set @rn=@rn+1 continue end begin try if @flag=0 begin exec master..[Generalization_Backup] @Database_Name=@db_name, @Bakup_Type=@operate_type, @Bakup_PATH_DIR=@bak_path, @Out_Message= @msg output if @msg='OK' update master..big_db set flag=1 where rn=@rn end end try begin catch if @msg='ok' set @msg='operate fail!' insert into backup_info(db_name,recovery_date,operate,msg) values(@db_name,convert(char(10),getdate(),120),@operate_type,@msg); end catch set @rn=@rn+1 end

    【3】差异备代码

    --备份策略
    /*
    6小时备份一次,一天备份4次
    */
    
    
    /*
    --查看当前所需要的备份库有多大
        select sum(size_GB)
            from
            (
                select t2.name,sum(t1.size*8.0/1024/1024) as size_GB ,row_number() over(partition by left(t2.name,len(t2.name)-7) order by cast(right(t2.name,6) as int) desc) as rn
                from master.sys.master_files t1
                join master.sys.databases t2 on t1.database_id=t2.database_id
                where isnumeric(right(t2.name,6))=1 and t2.name not in ('tempdb','model')
                group by t2.name
                union all
                select t2.name,sum(t1.size*8.0/1024/1024) as size_GB,row_number() over(partition by t2.name order by t2.name) as rn
                from master.sys.master_files t1
                join master.sys.databases t2 on t1.database_id=t2.database_id
                where isnumeric(right(t2.name,6))=0 and t2.name not in ('tempdb','model')
                group by t2.name
                
            ) t2
            where  rn=1
            
    --查看磁盘剩余空间
        exec master..xp_fixeddrives
    */
    
    use master
    go
    --select * from master..small_db
    --select * from master..big_db
    --select * from master..backup_info
    --select * from master..tran_db
    --select * from master..diff_db
    
    set nocount on
    go
    --【1】构造临时表
        if object_id('diff_db') is not null
            drop table master..diff_db
        select *,row_number() over(order by name) as rn,0 as flag
        into master..diff_db
        from 
        (
            select name,size_GB from master..big_db
            union all
            select name,size_GB from master..small_db
        ) t
    
    --【2】delcare 定义相关变量 与 初始化
    use master
    go
        declare @bak_path varchar(300),@db_name varchar(300),@operate_type varchar(50)
        declare @rn int,@rn_count int
        declare @flag int
        declare @msg varchar(4000)
        
        set @bak_path='d:DB_AUTO_BAK'
            
        
        
    --【3】差异    备份
        set @rn=1
        select @rn_count=count(1) from master..diff_db
        
        while @rn<=@rn_count
        begin
                
                select @db_name=name,@flag=flag 
                from master..diff_db where rn = @rn
                
                 if exists(select 1 from msdb..backupset where type='D' and datediff(day,backup_start_date,getdate())<=7 and  database_name=@db_name) and @db_name!='master'
                set @operate_type='diff'
                
                begin try
                if @flag=0
                begin
                    exec master..[Generalization_Backup] 
                    @Database_Name=@db_name,
                    @Bakup_Type=@operate_type,
                    @Bakup_PATH_DIR=@bak_path,
                    @Out_Message= @msg output    
                    if @msg='OK' 
                        update  master..diff_db set flag=1  where rn=@rn
                end
                end try
                begin catch
                if @msg='ok'
                        set @msg='operate fail!'
                    insert into backup_info(db_name,recovery_date,operate,msg) values(@db_name,convert(char(10),getdate(),120),@operate_type,@msg);
                end catch
    
                set @rn=@rn+1
        end
        

    【4】事务日志备代码

    use master;
    --每15分钟备份一次
    
    --【2】delcare 定义相关变量 与 初始化
    
    
            declare @bak_path varchar(300),@db_name varchar(300),@operate_type varchar(50)
            declare @rn int,@rn_count int
            declare @flag int
            declare @msg varchar(4000)
            
            set @bak_path='d:DB_AUTO_BAK'
                
    if object_id('small_db') is not null and object_id('big_db') is not null and object_id('backup_info') is not null
    begin
    
        if object_id('tran_db') is not null
            drop table tran_db
            
        select t1.*,row_number() over(order by t1.name ) as rn
        into master..tran_db
        from (
            select name,size_GB from master..small_db
            union all
            select name,size_GB from master..big_db
        ) t1
        join master.sys.databases t2 on t1.name=t2.name
        where t2.recovery_model_desc!='simple'
    
            
            
    --【3】数据库    tran 备份
    
        
            set @rn=1
            select @rn_count=count(1) from master..tran_db
            
            while @rn<=@rn_count
            begin
                    
                select @db_name=name  from master..tran_db where rn = @rn
                    
                if exists(select 1 from msdb..backupset where type='D' and datediff(day,backup_start_date,getdate())<=7 and  database_name=@db_name) 
                begin    
    
                    set @operate_type='tran'
                    
                    begin try
    
                        print @rn
                        exec master..[Generalization_Backup] 
                        @Database_Name=@db_name,
                        @Bakup_Type=@operate_type,
                        @Bakup_PATH_DIR=@bak_path,
                        @Out_Message= @msg output    
                        if @msg!='OK' 
                            insert into backup_info(db_name,recovery_date,operate,msg) values(@db_name,convert(char(20),getdate(),120),@operate_type,@msg);
                    end try
                    begin catch
                        insert into backup_info(db_name,recovery_date,operate,msg) values(@db_name,convert(char(10),getdate(),120),@operate_type,@msg);
                    end catch
                end
                set @rn=@rn+1
                
            end
            
        
    
    end
    
    --select * from  backup_info

    【5】删除过期备份文件

    --
    /*
    每天一次,5点开始执行
    */
    --[1]get #temp1 tale 
    use master
    go
    if object_id('diff_db') is not null
    begin
        select name,row_number() over(order by name)  as  rn
        into #temp1
        from master..diff_db
    
        DECLARE @oldDate DATETIME
        declare @bak_path nvarchar(300)
        declare @rn int,@rn_count int
        declare @db_name varchar(200),@URL varchar(1000)
    
        set @rn=1
        select @rn_count=count(1) from #temp1
        set @bak_path=N'd:DB_AUTO_BAK'
        SET @oldDate = GETDATE()-7
        
    --sql server2005
    
        while @rn<=@rn_count
        begin
            select @db_name=name   from #temp1 where @rn=rn
            set @URL=@bak_path+@db_name+''
            
            EXECUTE MASTER.dbo.xp_delete_file 
            0, --0: 备份文件,1: 维护计划文本报告
            @URL, --文件路径
            N'trn', --文件扩展名
            @oldDate --在此时间之前的文件一律删除
            
            
            EXECUTE MASTER.dbo.xp_delete_file 
            0, --0: 备份文件,1: 维护计划文本报告
            @URL, --文件路径
            N'bak', --文件扩展名
            @oldDate --在此时间之前的文件一律删除
            
            
            
            set @rn=@rn+1
        end
    
    --sql server 2008及以上
    /*
        EXECUTE MASTER.dbo.xp_delete_file 
            0, --0: 备份文件,1: 维护计划文本报告
            @URL, --文件路径
            N'trn', --文件扩展名
            @oldDate, --在此时间之前的文件一律删除
            1 -- 0: URL下的文件   1:URL下的文件及所有子文件夹下的文件
    */
    end    
        
        

    【6】收缩日志

    /*
    /*
    每天一次,5点开始执行
    */
    */
    
    use master
    go
    --drop table #temp2
        SELECT t1.name AS logic_name,t2.name ,row_number() over(order by t2.name)  as  rn
        into #temp2
        FROM master.sys.master_files t1  
        JOIN master.sys.databases t2 ON t1.database_id=t2.database_id
        WHERE type_desc='LOG' 
    
        DECLARE @oldDate DATETIME
        declare @bak_path nvarchar(300)
        declare @rn int,@rn_count int
        declare @db_name varchar(200),@logic_name VARCHAR(200)
    
        set @rn=1
        select @rn_count=count(1) from #temp2
        
        
        while @rn<=@rn_count
        begin
            select @db_name=name,@logic_name=logic_name   from #temp2 where @rn=rn
            
            EXEC('USE '+@db_name+';dbcc shrinkfile('+@logic_name+',10);')
            set @rn=@rn+1
        end
        

    【7】清理备份记录 和 作业执行记录

    --清理固定时间之前所有的备份历史记录
    USE msdb;  
    GO  
    EXEC sp_delete_backuphistory @oldest_date = '2020-08-01';  
    

    --清理固定时间之前所有作业的历史记录
    USE msdb ; GO EXEC dbo.sp_purge_jobhistory @oldest_date='2020-08-01'; GO

    参考官网:

    sp_delete_backuphistory    sp_purge_jobhistory
  • 相关阅读:
    MVC身份验证及权限管理
    EasyPR--开发详解
    ASP.NET 安全认证
    将Excel导入到数据中
    ExtJS 4 树
    ExtJS 4 表单
    ExtJS 4 Grids 详解
    ExtJS 4 类系统
    第4章 类型基础 -- 4.1 所有类型都从System.Object派生
    随滚动条浮动的链接块层
  • 原文地址:https://www.cnblogs.com/gered/p/13447780.html
Copyright © 2011-2022 走看看