MS SQL Server 2008使用SMO还原DB会破坏resourceDB

时间:2014-12-12 15:21:44

标签: c# sql-server sql-server-2008 smo

我目前正面临一个与我的某个数据库实例存在非常奇怪的问题。 我编写了一个小应用程序来从一个MS SQL Server 2008实例备份一组数据库,并在第二个实例上的现有DB上恢复相同的集合。这两个实例都在Windows Server 2008R2计算机上运行。使用内置于简单C#Windows窗体中的MS SQL Server管理对象(SMO)完成备份和还原。

在第二个实例上恢复数据库后,我遇到了一些问题:

  • 右键单击数据库并选择“属性”,会显示以下错误消息 | - >无法显示请求的对话框(SqlMgmt) | - >执行Transact-SQL语句或批处理时发生异常     | - >由于数据移动,无法继续使用NOLOCK扫描。 (Microsoft SQL Server,错误:601)
  • 我无法打开活动监视器(相同的错误消息)
  • SQL错误日志报告资源数据库已损坏(“SQL Server检测到基于逻辑一致性的i / O错误:无效保护选项。它发生在读取页面...数据库ID ...偏移量时。 ..在文件...“)
  • SELECT SERVERPROPERTY('ResourceVersion')命令给出版本号
  • 从另一个SQL Server复制资源数据库的mdf和ldf文件(并重新启动服务)解决了问题

现在我知道资源数据库应该是只读的,并且在HW问题之外,它不会被破坏,这真让我感到疑惑,我在哪里陷入困境?为什么更换资源数据库会解决我的问题?

有没有人遇到过同样的问题?

更新: 使用以下命令执行备份:

Backup backup = new Backup();
backup.Action = BackupActionType.Database;
backup.Database = databaseName;
backup.CopyOnly = true;
backup.Checksum = true;
backup.BackupSetDescription = "Full backup of " + databaseName;
backup.BackupSetName = databaseName + " Backup";
backup.Initialize = true;
string backupFilePath = backupLocation + "\\" + databaseName + ".bak";
backup.Devices.AddDevice(backupFilePath, DeviceType.File);
Microsoft.SqlServer.Management.Smo.Server smoServer = new Server(connectionString);
smoServer.ConnectionContext.StatementTimeout = 0;
smoServer.ConnectionContext.AutoDisconnectMode = AutoDisconnectMode.NoAutoDisconnect;
smoServer.ConnectionContext.Connect();
backup.SqlBackup(smoServer);
smoServer.ConnectionContext.Disconnect();

..并验证如下:

Restore restore = new Restore();
string backupFilePath = backupLocation + "\\" + databaseName + ".bak";
Microsoft.SqlServer.Management.Smo.Server smoServer = new Server(connectionString);
BackupDeviceItem deviceItem = new BackupDeviceItem(backupFilePath, DeviceType.File);
restore.Devices.Add(deviceItem);
bool verified = restore.SqlVerify(smoServer);

恢复通过以下方式执行:

Microsoft.SqlServer.Management.Smo.Server smoServer = new Server(connectionString);
smoServer.ConnectionContext.StatementTimeout = 0;
smoServer.ConnectionContext.AutoDisconnectMode = AutoDisconnectMode.NoAutoDisconnect;
smoServer.ConnectionContext.Connect();
Database db = smoServer.Databases[databaseName];
Restore restore = new Restore();
string backupFilePath = backupLocation + "\\" + databaseName + ".bak";
BackupDeviceItem deviceItem = new BackupDeviceItem(backupFilePath, DeviceType.File);
restore.Devices.Add(deviceItem);
restore.Database = databaseName;
restore.Action = RestoreActionType.Database;
restore.ReplaceDatabase = true;
restore.SqlRestore(smoServer);
db = smoServer.Databases[databaseName];
db.SetOnline();
smoServer.Refresh();
db.Refresh();
Restore rest = new Restore();
rest.Devices.AddDevice(backupFilePath, DeviceType.File);
bool verifySuccessful = rest.SqlVerify(smoServer);
smoServer.ConnectionContext.Disconnect();

我知道一旦备份或恢复完成后,连接实际上应断开连接,并且实际连接和断开连接正确,这个带手动连接和断开连接的最新版本是一个实验来检查最终结果是否有任何差异。没有。

备份和恢复都在后台工作程序中执行,在try ... catch循环中执行,并且不会引发异常。

我相信这些参数是不言自明的,但如果有些不清楚,我会很乐意澄清。

更新2 : 经过更彻底的测试后,我无法重现资源数据库损坏问题。当我第一次尝试恢复时,我正在把这个归咎于行星对齐。 感谢Jeroen的帮助和提示!

1 个答案:

答案 0 :(得分:1)

没有理由认为您的备份/恢复与数据库失败有关。遇到腐败时,请执行常规舞蹈:运行DBCC CHECKDB,检查硬件是否有错误,查看是否有cumulative updates适用于您的版本,可能会解决损坏问题。如果你可以通过恢复数据库来一致地重现错误,即使在具有完全相同版本的SQL Server的另一台机器上也是如此,你可能已经发现了MS感兴趣的错误。否则,我会花很长时间来看看硬件

更换资源数据库修复它的事实并不意味着你已经发现并修复了潜在的问题,只是它已经不再被破坏了。这仍然没有告诉你腐败的原因。

只是为了完整性:没有你没有手动编辑数据库文件(通过DBCC PAGE或只是通过在SQL Server外写入它)是数据库损坏的正当理由,所以你绝对不会“搞砸”。