4

我目前正在构建单元测试,以测试某些类是否正确编辑了 sql server 2005 数据库。为此,我从我们的生产中创建了一小部分数据,并将其存储为备份文件。每当单元测试需要确保它具有干净的数据库状态时,它都会调用一个恢复例程,该例程基本上调用以下 sql:

RESTORE DATABASE database FROM DISK = 'c:\test\backup.bak' WITH REPLACE, NORECOVERY

这通常有效,并且速度不错。当我说正常时,这是因为有时数据库卡在“恢复”模式会导致错误消息看起来像这样(假设它是一个 Alter 命令):

ALTER DATABASE is not permitted while a database is in the Restoring state.

这意味着如果第一次失败,那么每个测试都会失败。我可以让数据库摆脱卡住状态,但是每次都这样做很烦人,这非常耗时,而且单元测试的重点是所以当我激活测试时我不需要任何东西。

我试图看看我是否可以通过 RESTORE 语法来避免它,但无法设置任何听起来可以解决问题的选项或标志。

有没有其他我可以使用的方法比 RESTORE 命令更安全?

更新: 我发现恢复失败主要发生在连接仍处于活动状态时。我通常使用以下结构处理该问题:

ALTER DATABASE MyDatabase SET Single_User WITH Rollback Immediate

-- Restore logic here

ALTER DATABASE MyDatabase SET Multi_User

这样做的问题是它只将所有连接限制为一个。有时,被迫关闭的连接之一会跳转到唯一一个空闲的连接,从而中断恢复并使其失败(或者这是我可以从我一直在阅读的文档和页面中收集到的内容)。

相反,在我开始还原逻辑之前,我尝试执行以下 SQL 命令:

Declare @spid int
Select @spid = min(spid) from master.dbo.sysprocesses
where dbid = db_id('Mydatabase')
While @spid Is Not Null
Begin
        Execute ('Kill ' + @spid)
        Select @spid = min(spid) from master.dbo.sysprocesses
        where dbid = db_id('Mydatabase') and spid > @spid
End

-- Do Restore Logic

http://geekswithblogs.net/AngelEyes/archive/2010/02/24/kill-connections-to-resote-db---sql-server.aspx

这部分代码进入并主动关闭所有连接,这为恢复逻辑提供了执行空间。但是,我不完全确定这是最好的方法,因为它不会阻止重新建立连接,可能会再次中断恢复过程。但到目前为止,我还没有看到证据表明这种情况已经发生。

4

2 回答 2

0

我发现成功的是首先回滚数据库,然后将其删除,从而解决已打开或链接到的任何问题:

if db_id('MyDatabase') is not null ALTER DATABASE MyDatabase SET SINGLE_USER 
    WITH ROLLBACK  IMMEDIATE

if db_id('MyDatabase') is not null drop database MyDatabase

create database MyDatabase
于 2012-09-12T13:57:49.470 回答
0

通过使用 usr 的建议并在恢复过程中编写脚本,我得到了它的工作。这个答案是为了关闭问题,以便访问者知道我找到了解决方案。该解决方案在原始问题中描述为更新。

于 2013-01-14T13:30:23.870 回答