首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当.bak文件中有多个备份点时使用SMO还原类

当.bak文件中有多个备份点时使用SMO还原类
EN

Stack Overflow用户
提问于 2014-08-12 00:01:31
回答 1查看 2K关注 0票数 6

我试图使用SMO编写一个简单的实用程序来备份/还原数据库。当备份文件中只有一个时间点时,此操作非常好。但是,当备份文件中定义了多个备份点(而不是备份集)时,SMO总是选择最早的备份,而SSMS总是选择最新的备份点。

这会导致数据的不正确恢复,我想知道是否有一个属性我可以设置,它将迫使restore类总是使用最新的备份点。

我已经尝试过设置Restore.ToPointInTime,但是由于数据库的恢复模型很简单,这是行不通的。

我找到了一篇描述如何选择还原时间的MSDN文章,其中包括将数据库设置为完全恢复模式:

http://technet.microsoft.com/en-us/library/ms179451(v=sql.105).aspx

在使用SMO时,这是否必要,是否有一种使用纯SMO (没有C# sql命令)的方法?我使用了Restore.ReadBackupHeaders,从它中我能够及时提取可用的备份点,但不能将其设置为在任何地方恢复。

编辑:

下面是我使用的代码,包括最近试图通过smo设置数据库恢复模型的更改:

代码语言:javascript
复制
    public void RestoreDatabase(string databaseName, string backupPath)
    {
        var server = new Server(GetServerConnection());

        //If the database doesn't exist, create it so that we have something
        //to overwrite.
        if (!server.Databases.Contains(databaseName))
        {
            var database = new Database(server, databaseName);
            database.Create();
        }

        var targetDatabase = server.Databases[databaseName];
        targetDatabase.RecoveryModel = RecoveryModel.Full;
        targetDatabase.Alter();

        Restore restore = new Restore();

        var backupDeviceItem = new BackupDeviceItem(backupPath, DeviceType.File);
        restore.Devices.Add(backupDeviceItem);
        restore.Database = databaseName;
        restore.ReplaceDatabase = true;
        restore.Action = RestoreActionType.Database;

        var fileList = restore.ReadFileList(server);

        var dataFile = new RelocateFile();
        string mdf = fileList.Rows[0][1].ToString();
        dataFile.LogicalFileName = fileList.Rows[0][0].ToString();
        dataFile.PhysicalFileName = server.Databases[databaseName].FileGroups[0].Files[0].FileName;

        var logFile = new RelocateFile();
        string ldf = fileList.Rows[1][1].ToString();
        logFile.LogicalFileName = fileList.Rows[1][0].ToString();
        logFile.PhysicalFileName = server.Databases[databaseName].LogFiles[0].FileName;

        restore.RelocateFiles.Add(dataFile);
        restore.RelocateFiles.Add(logFile);

        var backupHeaderInfo = GetBackupHeaderInformation(restore, server);
        var latestBackupDate = backupHeaderInfo.Max(backupInfo => backupInfo.BackupStartDate);

        restore.ToPointInTime = latestBackupDate.ToString();

        server.KillAllProcesses(databaseName);

        restore.SqlRestore(server);
    }

看上去这是个好办法,不过这句话

代码语言:javascript
复制
targetDatabase.RecoveryModel = RecoveryModel.Full

似乎没有做任何改变恢复模型的操作,导致我仍然得到以下异常:

对于使用简单恢复模型的数据库,不支持STOPAT选项。还原数据库正在异常终止。

编辑2:

我加了一行

代码语言:javascript
复制
targetDatabase.Alter();

并解决了不更新问题。但是,它现在恢复,但使数据库处于还原模式,因此无法进行查询。

编辑3:

我通过将Restore.FileNumber属性设置为BackupHeaders中位置的最大值来实现代码的工作,虽然我仍然不确定为什么备份文件有多个备份头,但只有一个备份集。

工作代码如下。

代码语言:javascript
复制
    public void RestoreDatabase(string databaseName, string backupPath)
    {
        var server = new Server(GetServerConnection());

        //If the database doesn't exist, create it so that we have something
        //to overwrite.
        if (!server.Databases.Contains(databaseName))
        {
            var database = new Database(server, databaseName);
            database.Create();
        }

        var targetDatabase = server.Databases[databaseName];
        targetDatabase.RecoveryModel = RecoveryModel.Full;
        targetDatabase.Alter();

        Restore restore = new Restore();

        var backupDeviceItem = new BackupDeviceItem(backupPath, DeviceType.File);
        restore.Devices.Add(backupDeviceItem);
        restore.Database = databaseName;
        restore.ReplaceDatabase = true;
        restore.NoRecovery = false;
        restore.Action = RestoreActionType.Database;

        var fileList = restore.ReadFileList(server);

        var dataFile = new RelocateFile();
        dataFile.LogicalFileName = fileList.Rows[0][0].ToString();
        dataFile.PhysicalFileName = server.Databases[databaseName].FileGroups[0].Files[0].FileName;

        var logFile = new RelocateFile();
        logFile.LogicalFileName = fileList.Rows[1][0].ToString();
        logFile.PhysicalFileName = server.Databases[databaseName].LogFiles[0].FileName;

        restore.RelocateFiles.Add(dataFile);
        restore.RelocateFiles.Add(logFile);

        var backupHeaderInfo = GetBackupHeaderInformation(restore, server);
        restore.FileNumber = backupHeaderInfo.Where(backupInfo => backupInfo.BackupType == BackupType.Database).Max(backupInfo => backupInfo.Position);

        server.KillAllProcesses(databaseName);

        restore.SqlRestore(server);

        targetDatabase.SetOnline();
    }
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-08-12 15:04:04

尽管你说你没有多个备份集,但我认为你有。从回放表的文档中:

备份集包含来自单个成功备份操作的备份。

因此,如果在单个备份文件中有“多个恢复点”,则有多个备份集。通过在msdb中查询dbo.backupset表来验证这一点

抛开学究,我认为您正在寻找还原对象上的FileNumber属性。这对应于the命令中的FILE = n备份集选项。为了得到最后一行,只需从ReadBackupHeaders调用中提取最后一行即可。

为了自己测试,通过SSMS执行一个恢复的动作,然后,而不是点击"ok",点击顶部的“脚本”按钮。我想你会在某个地方看到一个FILE = <some number>

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25254269

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档