我编写了一个存储过程,在游标中遍历我的数据库,恢复最近的备份,运行 checkdb,删除恢复的数据库,然后继续下一个。我发现在此过程中,在任何给定时间都会恢复几个数据库,这会占用太多磁盘空间,无法在我的大型数据库上运行。该过程完成后,所有数据库都将被删除,并且不会留下任何东西。我已经检查并仔细检查了我在光标内有删除数据库的步骤,但这没有帮助。
我在光标中有这段代码:
SET @DropCommand = 'IF DB_ID(''' + @CursorRestoreName + ''') IS NOT NULL
BEGIN
ALTER DATABASE [' + @CursorRestoreName + '] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
DROP DATABASE [' + @CursorRestoreName + '];
END';
EXEC sp_executesql @DropCommand
我还添加了一条PRINT @DropCommand
语句来验证此代码块是否正在执行,并且确实如此。
由于这不起作用,我在第一个游标中添加了另一个游标,以浏览完整的数据库列表以尝试使用 drop 命令,以清理以前的恢复。这仍然具有相同的效果:在此过程中,在给定时间服务器上存在多个数据库还原,然后所有数据库都已被删除。
您是否有任何建议我可以实施,以便在继续下一次还原之前实际删除还原的数据库?或者也许有解决此问题的建议?
可能发生的情况是,在您将其设置为 SINGLE_USER 后,另一个会话正在连接到数据库。始终在将数据库设置为 SINGLE_USER 之前连接到数据库,否则您无法保证您将是单个用户。但是你不能删除你连接的数据库,所以 SINGLE_USER 不是正确的状态。
虽然将数据库设置为 OFFLINE 将起作用,但请注意删除 OFFLINE 数据库不会删除数据库文件。然后您将无法恢复,因为数据库文件一直存在。默认情况下,您无权删除数据库文件,也不应该真正需要它们。
RESTRICTED_USER 可能是在删除数据库之前放置数据库的最佳状态。例如
https://learn.microsoft.com/en-us/sql/t-sql/statements/alter-database-transact-sql-set-options?view=sql-server-2017
几年后,我明白了这一点。这是那些面对面的时刻之一;多年来,一个简单的遗漏命令导致我多次研究这个问题,但它从来没有足够高的优先级来花很多时间。这一次,我找到并修复了它。
正如我在问题中提到的,我正在使用游标循环数据库并运行恢复命令。在游标中,我根据需要恢复的文件构建恢复命令,并将该字符串存储在 VARCHAR 变量中。然后我使用 EXEC 执行该字符串,然后在验证恢复的数据库后,我将其删除。我的代码的问题在于,在游标循环开始时,我没有将命令字符串变量重置为 '',因此我将下一个数据库的恢复命令附加到前一个循环中的现有命令。因此,在十个数据库的最后一个循环中,该命令在最终运行 DROP DATABASE 命令之前恢复了所有十个数据库。