SQL Server中使用数据库快照的方式来完成测试环境中数据库的轻量级备份还原操作

简介: 原文:SQL Server中使用数据库快照的方式来完成测试环境中数据库的轻量级备份还原操作  在开发或者测试环境的数据库中,经常会发现有开发或者测试人员误删除表或者数据的情况,对于开发或者测试库,一般都没有安排定时的备份任务去备份数据库,一方面是由于存储资源有限,不太可能给开发或者测试环境准备大量的存储空间,二是必要性不是很强,开发或者测试库的数据库对象变化太多,通过还原备份的方式又有可能冲掉其最近新建的数据库对象。
原文: SQL Server中使用数据库快照的方式来完成测试环境中数据库的轻量级备份还原操作

 

在开发或者测试环境的数据库中,经常会发现有开发或者测试人员误删除表或者数据的情况,
对于开发或者测试库,一般都没有安排定时的备份任务去备份数据库,
一方面是由于存储资源有限,不太可能给开发或者测试环境准备大量的存储空间,
二是必要性不是很强,开发或者测试库的数据库对象变化太多,通过还原备份的方式又有可能冲掉其最近新建的数据库对象。
但是不得不面对的问题就是个别人在执行update或者delete操作的时候“忘了加where条件”这种事情的发生。

这是开发或者测试环境的一个痛点,相信多数人都经历过,
当面对开发人员过来说“我刚才delete表的时候忘了加where条件,结果全删了,能不能还原一下?”这个问题的时候,
实则有点尴尬,只能告知无法还原,sqlserver不支持闪回功能,又因为测试数据库没有备份,确实无能为力。
此时,开发人员往往会报以鄙视+无奈的眼神,作为冒牌DBA,确实难以相助。

为了切实地解决这个问题,同时又能够以最小的代价来实现,可以定时给测试库打快照的这种轻量级的方式来解决误删除数据的问题。
一是快照占用的空间并不大,
二是可以通过轻量级的方式去还原单个表的数据
花了点时间,写了个全实例下用户数据库的生成快照操作,可以安排一个定时任务来完成定时对数据库生成快照的方式来做一个轻量级的备份。
因此就可以方便地解决执行update或者delete操作的时候“忘了加where条件”误删数据或者表的情况。

 

通过定时对开发环境的数据库打快照,一旦出现误删数据的情况,可以根据最近的快照中的数据还原误删的数据,同时可以根据实际情况,删除创建的已过期的快照。

 

简单测试了一下,应该可以达到目的,没有做完整的测试,原理很简单,双层while循环,就是通过循环每一个数据库对应的物理文件,动态生成一个创建数据库快照的语句
此种方式仅适应于开发或者测试环境数据库的轻量级备份,不适应于生产环境。

--生成全实例下的数据库快照
create proc [dbo].[CreateSnapshotForBackUp]
(
    --数据库快照文件位置
    @p_FilePath varchar(500),
    --保留最近N个小时之内创建的快照,单位为小时
    @p_RetainTime int
)
as
begin
    set nocount on;

    declare @strSql            varchar(2000)
    declare @strDatetime    varchar(20)
    declare @strDBFileName    varchar(200)

    set @strDatetime =  replace(replace(replace(CONVERT(varchar, getdate(), 120 ),'-',''),' ',''),':','')
    

    if object_id('tempdb..#databaseName') is not null
    begin 
        drop table #databaseName
    end

    select name 
    into #databaseName  
    from  sys.databases where database_id>6 and source_database_id is null 
    

    declare @databaseName varchar(200);
    declare @databaseCnt int;
    select @databaseCnt = count(1) from #databaseName;

    while @databaseCnt>0
    begin

        select top 1 @databaseName = name from #databaseName

        if object_id('tempdb..#dbFiles') is not null
        begin 
            drop table #dbFiles
        end

        select concat('(','name = ' , name , ',FileName = ''',@p_FilePath,name,'_',@strDatetime,'.ss'' )' ) as strFileName
        into #dbFiles
        from sys.sysaltfiles 
        where  dbid=db_id(@databaseName) and status = 2

        DECLARE @dbFileCnt int = 0;
        SELECT @dbFileCnt = COUNT(1) FROM  #dbFiles
        while @dbFileCnt>0
        begin
            select top 1 @strDBFileName = strFileName from #dbFiles;
            set @strSql=CONCAT(@strSql,',',@strDBFileName,char(10));
            delete top (1) from #dbFiles;
            select @dbFileCnt = count(1) from #dbFiles;
        end

        set @strSql=stuff(@strSql,1,1,'')

        set @strSql = CONCAT('create database ' ,@databaseName,'_',@strDatetime, char(10),
                             ' on ' , char(10), @strSql
                             ,'as snapshot of ' , @databaseName)


        begin try
            print @strSql
            exec(@strSql)
            select @databaseName+'snapshot create successful:'+@databaseName+@strDatetime
            set @strSql = ''
        end try
        begin catch
            select 'snapshot create fail'
            throw
        end catch

        delete top (1) from #databaseName
        select @databaseCnt = count(1)  from #databaseName
    end


    --删除过期的数据库快照
    begin try
        if object_id('tempdb..#snapshotname') is not null
            drop table #snapshotname

        select name 
        into #snapshotname 
        from sys.databases 
        where source_database_id is not null and create_date<dateadd(hh,-@p_RetainTime,getdate());

        declare @cnt int = 0;
        declare @strDBName varchar(200) = ''
        declare @strDropDatabase varchar(max) =  ''
        select @cnt = count(1) from #snapshotname
        while @cnt>0
        begin
            select top 1 @strDBName = name from #snapshotname;
            set @strDropDatabase = 'drop database ' +@strDBName;
            print @strDropDatabase
            exec (@strDropDatabase);
            delete top (1) from #snapshotname;
            select @cnt = count(1) from #snapshotname
        end

    end try
    begin catch
        select N'snapshot delete fail'
        throw
    end catch

end

 

 

 

实话讲,已经完全忘记了T-SQL中游标的语法了,通过while循环临时表的方式,也可以达到游标循环的效果,并且这种语法逻辑结构上更清晰简便,根本不会忘记,呵呵。

 

目录
相关文章
|
5月前
|
关系型数据库 MySQL 数据库
阿里云数据库RDS费用价格:MySQL、SQL Server、PostgreSQL和MariaDB引擎收费标准
阿里云RDS数据库支持MySQL、SQL Server、PostgreSQL、MariaDB,多种引擎优惠上线!MySQL倚天版88元/年,SQL Server 2核4G仅299元/年,PostgreSQL 227元/年起。高可用、可弹性伸缩,安全稳定。详情见官网活动页。
991 152
|
5月前
|
关系型数据库 MySQL 数据库
阿里云数据库RDS支持MySQL、SQL Server、PostgreSQL和MariaDB引擎
阿里云数据库RDS支持MySQL、SQL Server、PostgreSQL和MariaDB引擎,提供高性价比、稳定安全的云数据库服务,适用于多种行业与业务场景。
804 156
|
7月前
|
SQL Java 关系型数据库
在 RDB 上跑 SQL------SPL 轻量级多源混算实践 1
SPL 支持通过 JDBC 连接 RDB,可动态生成 SQL 并传参,适用于 Java 与 SQL 结合的各类场景。本文以 MySQL 为例,演示如何配置数据库连接、编写 SPL 脚本查询 2024 年订单数据,并支持参数过滤和 SQL 混合计算。脚本可在 IDE 直接执行或集成至 Java 应用调用。
|
5月前
|
SQL 人工智能 Linux
SQL Server 2025 RC1 发布 - 从本地到云端的 AI 就绪企业数据库
SQL Server 2025 RC1 发布 - 从本地到云端的 AI 就绪企业数据库
521 5
SQL Server 2025 RC1 发布 - 从本地到云端的 AI 就绪企业数据库
|
4月前
|
SQL 存储 监控
SQL日志优化策略:提升数据库日志记录效率
通过以上方法结合起来运行调整方案, 可以显著地提升SQL环境下面向各种搜索引擎服务平台所需要满足标准条件下之数据库登记作业流程综合表现; 同时还能确保系统稳健运行并满越用户体验预期目标.
294 6
|
5月前
|
关系型数据库 分布式数据库 数据库
阿里云数据库收费价格:MySQL、PostgreSQL、SQL Server和MariaDB引擎费用整理
阿里云数据库提供多种类型,包括关系型与NoSQL,主流如PolarDB、RDS MySQL/PostgreSQL、Redis等。价格低至21元/月起,支持按需付费与优惠套餐,适用于各类应用场景。
|
6月前
|
SQL 关系型数据库 Java
SQL 移植--SPL 轻量级多源混算实践 7
不同数据库的 SQL 语法存在差异,尤其是函数写法不同,导致 SQL 移植困难。SPL 提供 sqltranslate 函数,可将标准 SQL 转换为特定数据库语法,实现 SQL 语句在不同数据库间的无缝迁移,支持多种数据库函数映射与自定义扩展。
|
5月前
|
SQL Oracle 关系型数据库
Oracle数据库创建表空间和索引的SQL语法示例
以上SQL语法提供了一种标准方式去组织Oracle数据库内部结构,并且通过合理使用可以显著改善查询速度及整体性能。需要注意,在实际应用过程当中应该根据具体业务需求、系统资源状况以及预期目标去合理规划并调整参数设置以达到最佳效果。
401 8
|
6月前
|
SQL 人工智能 Java
用 LangChain4j+Ollama 打造 Text-to-SQL AI Agent,数据库想问就问
本文介绍了如何利用AI技术简化SQL查询操作,让不懂技术的用户也能轻松从数据库中获取信息。通过本地部署PostgreSQL数据库和Ollama模型,结合Java代码,实现将自然语言问题自动转换为SQL查询,并将结果以易懂的方式呈现。整个流程简单直观,适合初学者动手实践,同时也展示了AI在数据查询中的潜力与局限。
761 8
|
8月前
|
SQL 关系型数据库 MySQL
Go语言数据库编程:使用 `database/sql` 与 MySQL/PostgreSQL
Go语言通过`database/sql`标准库提供统一数据库操作接口,支持MySQL、PostgreSQL等多种数据库。本文介绍了驱动安装、连接数据库、基本增删改查操作、预处理语句、事务处理及错误管理等内容,涵盖实际开发中常用的技巧与注意事项,适合快速掌握Go语言数据库编程基础。
665 62