从另一台服务器的文件中自动恢复 SQL Server 数据库

tor*_*yan 5 sql-server maintenance

我们的日常任务是使用相关生产数据库的备份覆盖许多开发数据库。备份由生产服务器上的维护计划生成,然后通过 FTP 传输到开发服务器。每天我们运行一个类似这样的 SQL 语句来覆盖每个数据库:

RESTORE DATABASE [Database1] 
FROM DISK = N'D:\path\to\Database1_backup_2015_02_05_190004_7401803.bak'
WITH FILE = 1,  NOUNLOAD,  REPLACE,  STATS = 10
GO
Run Code Online (Sandbox Code Playgroud)

每次我们运行它时,我们都必须用正确的最新文件替换文件名。我想以某种方式自动执行此操作以最大程度地减少操作员错误的机会。问题是我们无法控制.bak文件的名称(尽管格式是一致的 - 数据库名称、日期、时间以及任何七位数),并且该文件夹通常包含几天的备份。

RLF*_*RLF 10

由于备份的所有详细信息都保存在 msdb 数据库中,因此您应该只从源服务器中提取备份文件名。

您可以从开发服务器创建链接服务器以访问生产服务器的 msdb 数据库。或者您可以使用 OPENQUERY 查询相同的数据。(OPENQUERY 可能更快,因为查询实际上是在生产服务器上运行的。)

例如:

SELECT * from OPENQUERY([LinkToPRD], 
     'EXEC database.dbo.ExecDailyRestore');
Run Code Online (Sandbox Code Playgroud)

这显示了运行不带参数的存储过程,这可能适合您的日常恢复计划。

如果您搜索“自动生成 sql server 数据库还原脚本”,您会发现很多脚本。Paul Brewer 的一个例子是sp_RestoreGene,您可以按原样使用或作为创建自己的ExecDailyRestore存储过程的基础。

https://paulbrewer.wordpress.com/sp_restoregene/

以下是 sp_restoregene 支持的参数:

    @Database SYSNAME = NULL,
    @TargetDatabase SYSNAME = NULL,
    @WithMoveDataFiles VARCHAR(2000) = NULL,
    @WithMoveLogFile  VARCHAR(2000) = NULL,
    @FromFileFullUNC VARCHAR(2000) = NULL,
    @FromFileDiffUNC VARCHAR(2000) = NULL,
    @FromFileLogUNC VARCHAR(2000) = NULL,
    @StopAt DATETIME = NULL,
    @StandbyMode BIT = 0,
    @IncludeSystemDBs BIT = 0,
    @WithRecovery BIT = 0,
    @WithCHECKDB BIT = 0,
    @WithReplace BIT = 0,
    @UseDefaultDatabaseBackupPath BIT = 0,
    @Log_Reference VARCHAR (250) = NULL,
    @LogShippingVariableDeclare BIT = 1,
    @LogShippingStartTime DATETIME = NULL,
    @LogShippingLastLSN VARCHAR(25) = NULL
Run Code Online (Sandbox Code Playgroud)

这是一个示例脚本:

RESTORE DATABASE db_workspace 
FROM DISK = 'X:\Backups\Temp\db_workspace.bak' WITH REPLACE, 
FILE = 1,CHECKSUM,NORECOVERY, STATS=10
, MOVE 'db_workspace' TO 'x:\data\db_workspace.mdf'
, MOVE 'db_workspace_log' TO 'x:\data\db_workspace_log.ldf'
, MOVE 'db_workspace_FG2' TO 'x:\data\db_workspace_FG2.ndf'
, MOVE 'db_workspace_FG1' TO 'x:\data\db_workspace_FG1.ndf'
Run Code Online (Sandbox Code Playgroud)


Zan*_*ane 8

这里的 DBA 可能会向我扔鸡蛋和西红柿,但无论如何我都会把它扔出去。

您可以使用和集成服务作业来运行它。首先创建一个 for Each 文件循环并将其设置为针对该位置的每个文件运行。 备份

将结果映射到变量。 多变的

然后在容器内创建并执行 SQL 任务。 美东时间

地图查询

完成后,您应该能够创建 SQL 作业并对其进行适当安排。我并不是说这是最好的解决方案,但它应该有效。

手绘


小智 5

这应该完全为您解决问题。显然,如果您要恢复到 mdf/ldf 名称不同的数据库,您可能需要稍微调整最终的恢复命令。这只是通过列出目录中的备份并根据模式进行选择来工作。我想我也可以让模式成为一个变量,但你明白了。

     DECLARE @FileName varchar(255), @PathToBackup varchar(255), @RestoreFilePath varchar(1000)

     DECLARE @Files TABLE (subdirectory varchar(255), depth int, [file] int)

     SET NOCOUNT ON

     SET @PathToBackup = 'D:\path\to'

     -- insert into our memory table using dirtree and a single file level
     INSERT INTO @Files
     EXEC master.dbo.xp_DirTree @PathToBackup,1,1

     SELECT TOP 1 
        @FileName = [subdirectory]
     FROM 
        @Files
     WHERE
        -- get where it is a file
        [file] = 1
     AND    
        subdirectory LIKE 'Database1_backup%.bak'
     ORDER BY
        -- order descending so newest file will be first by naming convention
        subdirectory DESC

    IF LEFT(REVERSE(@PathToBackup), 1) != '\'
    BEGIN
        SET @PathToBackup = @PathToBackup + '\'
    END

    SET @RestoreFilePath = @PathToBackup + @FileName

    SELECT @RestoreFilePath

    RESTORE DATABASE [Database1] 
    FROM DISK = @RestoreFilePath
    WITH FILE = 1,  NOUNLOAD,  REPLACE,  STATS = 10
Run Code Online (Sandbox Code Playgroud)