如何使用SMO for .NET还原多个事务日志

时间:2018-12-10 19:23:40

标签: c# .net sql-server smo

我正在使用数据库应用程序来还原带有事务日志的数据库。我正在使用SQL Server管理对象(SMO)库。

此应用程序的要求使其得以实现,因此我必须在单独的进程中还原数据库备份文件及其事务日志。我可以毫不费力地恢复备份文件,但是在恢复事务日志时遇到了一个问题:

        public void RestoreTransactionLogs(Server srv, DirectoryInfo filePath, DatabaseType dbType)
        {
            Restore res = new Restore()
            {
                Database = dbType.ToString(),
                Action = RestoreActionType.Log,
                ReplaceDatabase = false
            };

            FileInfo[] files = filePath.Parent.GetFiles("*.trn");

            foreach (FileInfo f in files)
            {
                res.Devices.AddDevice(f.FullName, DeviceType.File);
            }           

            try
            {
                res.SqlRestore(srv);
            }
            catch (SmoException ex)
            {
                Log.Fatal("An SMO Exception has occurred when restoring the database: " + dbType.ToString() + ": " + ex.Message);
                throw ex;
            }
            catch (Exception ex)
            {
                Log.Fatal("An exception has occurred when restoring the database:  " + dbType.ToString() + ": " + ex.Message);
                throw ex;
            }

        }

使用测试备份文件和20个事务日志,我遇到以下错误:

  

SmoException:System.Data.SqlClient.SqlError:加载的媒体   “ D:\ Test文件夹\ testDatabase \ log_00001.trn”的格式设置为支持   1个媒体家庭,但预计20个媒体家庭   备份设备规范。

我觉得我没有将事务日志正确地添加到我的设备集合中,或者应该以其他方式添加它们,但是不确定在哪里检查。来自MSDN的用于事务日志的文档很稀少,而且我在网上找不到很多。谢谢!

2 个答案:

答案 0 :(得分:0)

我认为您的问题是您不能仅还原事务日志。您必须先从完整备份开始,然后再应用事务日志。这必须在db处于无恢复状态时发生,因此在完全备份还原和事务日志还原之间不会对db进行其他任何更改。另外,请记住,您必须按照处理顺序来应用事务日志。

这是我根据此处的doco示例进行的工作:

https://docs.microsoft.com/en-us/sql/relational-databases/server-management-objects-smo/tasks/backing-up-and-restoring-databases-and-transaction-logs?view=sql-server-ver15

using (SqlConnection connection = new SqlConnection(connectionString))
{
    var server = new Server(new ServerConnection(connection));
    Database targetDb = server.Databases["TargetDbName"];

    // Make sure your user has ALTER ANY CONNECTION rights for this
    // not needed if you can be sure db is not in use
    server.KillAllProcesses(targetDb.Name);
    targetDb.SetOffline();

    Restore restoreDB = new Restore();
    restoreDB.Database = targetDb.Name;
    restoreDB.Action = RestoreActionType.Database;
    restoreDB.ReplaceDatabase = true;

    // Restore the full backup first
    var fullBackupDevice = new BackupDeviceItem("fullBackupFile.bak", DeviceType.File);
    restoreDB.Devices.Add(fullBackupDevice);
    restoreDB.NoRecovery = true;
    restoreDB.SqlRestore(server);
    restoreDB.Devices.Remove(fullBackupDevice);

    // Get the first taken transaction log file
    var firstTransactionBackupDevice = new BackupDeviceItem("firstTrnFile.trn", DeviceType.File);
    restoreDB.Devices.Add(firstTransactionBackupDevice);
    restoreDB.SqlRestore(server);
    restoreDB.Devices.Remove(firstTransactionBackupDevice);

    // Get the second taken transaction log file
    var secondTransactionBackupDevice = new BackupDeviceItem("secondTrnFile.trn", DeviceType.File);
    restoreDB.Devices.Add(secondTransactionBackupDevice);
    // You have to set this flag to false before the last file you will restore
    // to return the db to the normal state
    restoreDB.NoRecovery = false;
    restoreDB.SqlRestore(server);
    restoreDB.Devices.Remove(secondTransactionBackupDevice);

    targetDb.SetOnline();
    server.Refresh();
}

我知道您的问题有点老了,您可能已经找到了解决方案,但是希望对其他人有所帮助。

答案 1 :(得分:-1)

您好,您可以在sql服务器中尝试以下脚本。不要更改目录文件路径。还要对“有恢复”和“无恢复”进行研究。

RESTORE DATABASE [DW] FROM DISK = 'G:\MSSQL\Data\FullBackups\db.bak' WITH NORECOVERY
Go
RESTORE DATABASE [DW] FROM DISK = 'G:\MSSQL\Data\DifferentialBackups\db.bak' WITH NORECOVERY
--repeat how many ever times if multiple based on time DB crashed.
GO
RESTORE DATABASE [DW] FROM DISK = 'G:\MSSQL\Data\TransactionLogs\db.bak' WITH NORECOVERY
--Final T-Log to exact point in time recovery.
RESTORE DATABASE [DW] FROM DISK = 'G:\MSSQL\Data\TransactionLogs\db.bak' WITH RECOVERY