使用NoRecovery选项从备份恢复数据库陷入恢复状态

问题描述 投票:0回答:1

我正在尝试从完整备份 (

.fbk
) 和快速备份 (
.qbk
) 恢复数据库。按照这个顺序

USE MASTER 
RESTORE DATABASE [" + DB_NAME + "] 
FROM DISK = \'" + BackupFile_Txt.Text + "\' WITH NORECOVERY";

声明,数据库卡在恢复状态。

当看到内部异常时,它说

数据库处于正在恢复状态时不允许进行 ALTER DATABASE
ALTER DATABASE 语句失败

当我打开 SSMS 时,它在数据库上显示“正在恢复”。

但是,当我仅尝试完整备份(

.fbk
)选项时,它恢复得很好(在本例中它使用“带恢复”)。

请参阅 WriteFile 方法中的 else if 条件。

private void WriteFile()
{
    try
    {
        // Creates Restore.sql file.
        string strTSQLFile = Environment.CurrentDirectory + "\\Restore.sql";
        FileInfo File = new FileInfo(strTSQLFile);

        StreamWriter Writer = File.CreateText();

        // Write open database  
        string strTemp;
        Writer.WriteLine("ALTER DATABASE [" + DB_NAME + "] SET SINGLE_USER WITH ROLLBACK IMMEDIATE");
        Writer.WriteLine("Go");

        if (Complete_Opt.Checked == true)           // Full restore
        {
            strTemp = "USE MASTER RESTORE DATABASE [" + DB_NAME + "] FROM DISK = \'" + BackupFile_Txt.Text + "\' WITH RECOVERY";
            Writer.WriteLine(strTemp);
        }
        else if (Differential_Opt.Checked == true)  // Quick restore
        {
            strTemp = "USE MASTER RESTORE DATABASE [" + DB_NAME + "] FROM DISK = \'" + BackupFile_Txt.Text + "\' WITH NORECOVERY";
            Writer.WriteLine(strTemp);
            Writer.WriteLine("GO");
            Writer.WriteLine("WAITFOR DELAY '00:00:10'");
            Writer.WriteLine("GO");
            Writer.WriteLine("ALTER DATABASE [" + DB_NAME + "] SET MULTI_USER");
            Writer.WriteLine("GO");
            Writer.WriteLine("ALTER DATABASE [" + DB_NAME + "] SET SINGLE_USER WITH ROLLBACK IMMEDIATE");
            Writer.WriteLine("Go");

            strTemp = "USE MASTER RESTORE DATABASE [" + DB_NAME + "] FROM DISK = \'" + txt_Quick.Text + "\' WITH RECOVERY";
            Writer.WriteLine(strTemp);
        }

        Writer.WriteLine("GO");
        Writer.WriteLine("ALTER DATABASE [" + DB_NAME + "] SET MULTI_USER");
        Writer.WriteLine("GO");

        Writer.WriteLine("USE PharmSpecDB");
        Writer.WriteLine("GO");

        Writer.WriteLine("IF EXISTS (SELECT * FROM sys.triggers WHERE name = 'D_TRG_TestResults')");
        Writer.WriteLine("BEGIN");
        Writer.WriteLine("DROP TRIGGER D_TRG_TestResults");
        Writer.WriteLine("END");
        Writer.WriteLine("GO");

        Writer.WriteLine("CREATE TRIGGER D_TRG_TestResults ON tblTestResults WITH ENCRYPTION INSTEAD OF DELETE AS BEGIN raiserror (50003,14,1)  END");
        Writer.WriteLine("GO");

        Writer.WriteLine("IF EXISTS (SELECT * FROM sys.triggers WHERE name = 'D_TRG_SampleIDParameter')");
        Writer.WriteLine("BEGIN");
        Writer.WriteLine("DROP TRIGGER D_TRG_SampleIDParameter");
        Writer.WriteLine("END");
        Writer.WriteLine("GO");

        Writer.WriteLine("CREATE TRIGGER D_TRG_SampleIDParameter ON tblSampleIDParameter WITH ENCRYPTION INSTEAD OF DELETE AS BEGIN raiserror (50003,14,1)   END");
        Writer.WriteLine("GO");

        Writer.WriteLine("IF EXISTS (SELECT * FROM sys.triggers WHERE name = 'D_TRG_TestRun')");
        Writer.WriteLine("BEGIN");
        Writer.WriteLine("DROP TRIGGER D_TRG_TestRun");
        Writer.WriteLine("END");
        Writer.WriteLine("GO");

        Writer.WriteLine("CREATE TRIGGER D_TRG_TestRun ON tblTestRun WITH ENCRYPTION INSTEAD OF DELETE AS BEGIN raiserror (50003,14,1) END");
        Writer.WriteLine("GO");

        Writer.WriteLine("IF EXISTS (SELECT * FROM sys.triggers WHERE name = 'D_TRG_ReviewApprove')");
        Writer.WriteLine("BEGIN");
        Writer.WriteLine("DROP TRIGGER D_TRG_ReviewApprove");
        Writer.WriteLine("END");
        Writer.WriteLine("GO");

        Writer.WriteLine("CREATE TRIGGER D_TRG_ReviewApprove ON tblReviewApprove WITH ENCRYPTION INSTEAD OF DELETE AS BEGIN raiserror (50003,14,1) END");
        Writer.WriteLine("GO");

        Writer.WriteLine("IF EXISTS (SELECT * FROM sys.triggers WHERE name = 'D_TRG_ActiveParamValues')");
        Writer.WriteLine("BEGIN");
        Writer.WriteLine("DROP TRIGGER D_TRG_ActiveParamValues");
        Writer.WriteLine("END");
        Writer.WriteLine("GO");

        Writer.WriteLine("CREATE TRIGGER D_TRG_ActiveParamValues ON tblActiveParamValues WITH ENCRYPTION INSTEAD OF DELETE AS BEGIN raiserror (50003,14,1) END");
        Writer.WriteLine("GO");

        Writer.WriteLine("IF EXISTS (SELECT * FROM sys.triggers WHERE name = 'D_TRG_ActivityLogger')");
        Writer.WriteLine("BEGIN");
        Writer.WriteLine("DROP TRIGGER D_TRG_ActivityLogger");
        Writer.WriteLine("END");
        Writer.WriteLine("GO");

        Writer.WriteLine("CREATE TRIGGER D_TRG_ActivityLogger ON tblActivityLogger WITH ENCRYPTION INSTEAD OF DELETE AS BEGIN raiserror (50003,14,1) END");
        Writer.WriteLine("GO");

        Writer.WriteLine("EXEC sp_revokedbaccess 'PharmSpecUsr'");
        Writer.WriteLine("EXEC sp_grantdbaccess  'PharmSpecUsr','PharmSpecUsr'");
        Writer.WriteLine("EXEC sp_addrolemember 'db_owner','PharmSpecUsr'");
        Writer.WriteLine("EXEC sp_addrolemember  'db_accessadmin','PharmSpecUsr'");
        Writer.WriteLine("EXEC sp_addrolemember  'db_datareader' ,'PharmSpecUsr'");
        Writer.WriteLine("EXEC sp_addrolemember 'db_datawriter ', 'PharmSpecUsr'");
        Writer.WriteLine("EXEC sp_addrolemember 'db_ddladmin', 'PharmSpecUsr'");
        Writer.WriteLine("EXEC sp_addrolemember 'db_securityadmin', 'PharmSpecUsr'");
        Writer.WriteLine("EXEC sp_addrolemember 'db_backupoperator','PharmSpecUsr'");
        Writer.WriteLine("GO");

        Writer.Close();
    }
    catch (Exception Exc)
    {
        throw Exc;
    }
}

我正在从 C# 代码执行此 SQL,如下所示:

try
{
    string strTSQLFile = Environment.CurrentDirectory + "\\Restore.sql";

    if (!File.Exists(strTSQLFile))
    {
        throw new FileNotFoundException();
    }

    using (StreamReader srSQL = new StreamReader(strTSQLFile))
    {
        string sqlLine;
        StringBuilder sqlString = new StringBuilder();

        while (!srSQL.EndOfStream)
        {
            sqlLine = srSQL.ReadLine();

            if (string.IsNullOrEmpty(sqlLine) == false)
            {
                // We don't actually execute the "GO" lines but can use them to determine when to call the executenonquery function
                if (string.Compare(sqlLine, "GO", true) == 0)
                {
                    // Make sure we have something to execute
                    if (string.IsNullOrEmpty(sqlString.ToString()) == false)
                    {
                        ServerActionResult.ConnectionContext.ExecuteNonQuery(sqlString.ToString());
                        System.Diagnostics.Debug.WriteLine(sqlString);
                    }

                    sqlString.Clear();
                }
                // Add the next line to the stringbuilder object
                else
                {
                    sqlString.AppendLine(sqlLine);
                }
            }
        }
    }
}
catch (Exception exc)
{
    throw exc;
}

调试:

当说

System.Diagnostics.Debug.WriteLine(sqlString);
时,它会打印:

ALTER DATABASE [PharmSpecDB] SET SINGLE_USER WITH ROLLBACK IMMEDIATE 

USE MASTER RESTORE DATABASE [PharmSpecDB] FROM DISK = 'C:\PharmBackup\Backup\PharmSpecDB_13-Nov-2024-12-42-57-717_Full.Fbk' WITH NORECOVERY
 WAITFOR DELAY '00:00:10'
                                                

编辑:

通过此评论及其在线内容“要恢复数据库并将其联机以便用户可以连接,您可以使用带有WITH RECOVERY选项的RESTORE DATABASE语句”。我正在尝试这样的事情,

strTemp = "USE MASTER RESTORE DATABASE [" + DB_NAME + "] FROM DISK = \'" + BackupFile_Txt.Text + "\' WITH NORECOVERY";
Writer.WriteLine(strTemp);
Writer.WriteLine("Go");
 strTemp = "USE MASTER RESTORE DATABASE [" + DB_NAME + "] FROM DISK = \'" + txt_Quick.Text + "\' WITH RECOVERY";
Writer.WriteLine(strTemp);
Writer.WriteLine("Go");

这样做就是抱怨,

“日志或差异备份无法恢复,因为没有文件 准备好前滚了。 恢复数据库正在终止 不正常地。 将数据库上下文更改为“主”。”

c# sql-server t-sql recovery
1个回答
0
投票

你尝试过这个吗?

数据库陷入“正在恢复”状态

可能是问题的答案,

卡在恢复状态

是...

您需要使用WITH RECOVERY选项,对您的数据库进行RESTORE 命令,作为恢复过程的一部分使您的数据库联机。

© www.soinside.com 2019 - 2024. All rights reserved.