C# 以编程方式从C还原ms sql系统数据库#

C# 以编程方式从C还原ms sql系统数据库#,c#,sql-server,backup,C#,Sql Server,Backup,虽然从恢复“正常”数据库的角度来处理编程备份恢复有很多问题和答案,但对系统数据库(如[master]、[msdb]、或[model])这样做会遇到许多不同的问题。我想知道是否有人对此有所贡献,特别是对于[master],但所有这些似乎都会引起问题。目前,我已经在单用户模式(整个服务)下启动了ms sql,以使用T3608标志恢复主数据库,但当我尝试对其运行恢复数据库查询时,这会断开与断开管道消息的连接。检查服务控制台services.msc会发现数据库服务不再运行 换句话说,运行此查询似乎会使s

虽然从恢复“正常”数据库的角度来处理编程备份恢复有很多问题和答案,但对系统数据库(如
[master]
[msdb]
、或
[model]
)这样做会遇到许多不同的问题。我想知道是否有人对此有所贡献,特别是对于
[master]
,但所有这些似乎都会引起问题。目前,我已经在单用户模式(整个服务)下启动了ms sql,以使用T3608标志恢复主数据库,但当我尝试对其运行
恢复数据库
查询时,这会断开与断开管道消息的连接。检查服务控制台
services.msc
会发现数据库服务不再运行

换句话说,运行此查询似乎会使sql server崩溃,而不会产生有用的消息结果

让我们看一些示例代码。查询生成代码如下所示:

string query = "RESTORE DATABASE @dbName FROM DISK " + 
    "= @backupPath WITH FILE = @fileID, REPLACE, ";
if (dataFileName != "") {
    query += "MOVE @dataFileName TO @dataFileLocation, ";
}
if (logFileName != "") {
    query += "MOVE @logFileName TO @logFileLocation, ";
}
query += "STATS=1";
SqlCommand cmdData = new SqlCommand(query, conn);
cmdData.Parameters.AddWithValue("@dbName", databaseName);
cmdData.Parameters.AddWithValue("@backupPath", filePath);
cmdData.Parameters.AddWithValue("@fileID", fileIndex);
if (dataFileName != "") {
    cmdData.Parameters.AddWithValue("@dataFileName", dataFileName);
    cmdData.Parameters.AddWithValue("@dataFileLocation", mdfPath);
}
if (logFileName != "") {
    cmdData.Parameters.AddWithValue("@logFileName", logFileName);
    cmdData.Parameters.AddWithValue("@logFileLocation", ldfPath);
}
cmdData.ExecuteNonQuery();
这是一个最简单的例子。FileIndex是一个包含备份文件索引的整数,此处未初始化的所有其他变量都是包含各种路径和名称的字符串。请注意,手动执行此类查询将生成预期结果(备份文件将被还原)

事件日志让事情变得更加奇怪。我注意到这一信息:

快照隔离或读取提交的快照在数据库“master”中不可用,因为SQL Server启动时使用了一个或多个未记录的跟踪标志,这些标志阻止启用数据库版本控制。使用快照隔离启动的事务将失败,在读提交快照下运行的查询将成功,但将返回到基于锁的读提交

它可能会抱怨T3608。事件日志还包含关于“成功恢复”的消息,但检查
DATA
文件夹的内容会发现,我的程序实际上并没有放回我手动删除的数据库文件,而是似乎什么也不做

我对SQLServer在这一点上的奇怪行为感到非常困惑。有人能解释一下这是怎么发生的吗

编辑:

对更改流程进行更多的挖掘和实验表明,实际上还需要msdb和模型数据库,否则SQL server将无法正常启动。因此,所有这三个数据库都需要存在才能恢复它们,而您只能恢复这三个数据库,我现在将以特殊的、复杂的、特定的方式来称之为特殊数据库,每一个数据库都是不同的

我还不确定到底是什么和如何做到的。互联网上有一大堆相互矛盾的建议,没有一个成文的程序能直接起作用

我发现ms sql保留了一个特殊的文件夹“模板数据”。这里有一组特殊数据库的模板。我可以将这些模板复制到real DATA文件夹中,以使运行的sql server能够从中恢复备份的特殊数据库

但是:这样做:在恢复非主特例(msdb和模型)的过程中,服务器仍然会自行终止。很可能实际上没有任何东西被修复

进一步检查日志文件会发现以下两个有趣的错误:

在数据库“model”中重新执行记录的操作期间,日志记录ID(32:151:1)处发生错误。通常,特定故障以前会作为错误记录在Windows事件日志服务中。从完全备份还原数据库,或修复数据库

在读取文件“E:\backupdb\MSSQL12.TBUINST\MSSQL\Template Data\modellog.ldf”的偏移量0000000000000000时,操作系统向SQL Server返回了错误5(访问被拒绝)。SQL Server错误日志和系统事件日志中的其他消息可能会提供更多详细信息。这是一种严重的系统级错误情况,威胁到数据库的完整性,必须立即纠正。完成完整的数据库一致性检查(DBCC CHECKDB)。这种误差可能是由许多因素造成的;有关详细信息,请参阅SQL Server联机丛书

为什么它现在试图读取“模板数据”中的内容?是否因为模板系统db或msdb db或模型db本身包含对模板模型/msdb/etc db的硬编码路径的引用,并且我必须发出移动命令?在恢复过程中,我何时/如何发布这些


我也意识到了这一点:假设我首先恢复了“主”数据库,并且它包含到其他特殊数据库的路径,那么为什么SQL server现在要在template data文件夹中搜索?毕竟,它在恢复主数据库时会重新启动,因此其中的路径现在应该是默认路径。更不用说,在每次恢复操作中,我都明确指定
.bak
文件和新的
.ldf
.mdf
文件的位置?这毫无意义。

主数据库还原完成后,SQL Server会自动停止。您需要在代码中处理由此产生的连接错误,重新启动SQL Server,然后继续还原其他系统数据库。

只有管理员可以还原备份。权限更改,管理员必须更改权限,普通用户才能访问数据库。普通用户可以卸载和附加数据库。@jdweng用户权限不是问题:此程序是以管理员身份启动的,因此它可以启动/停止sql server,无论使用各种配置标志执行所有备份还原需要多少次。此外,它还预先检查是否在SQL server上具有管理员权限。如果没有,则要求用户在每次重新连接到数据库时提供SA密码。我们发现,当任何用户存档数据库时,该文件的Windows权限将变为只读。这个