代码之家  ›  专栏  ›  技术社区  ›  user281693

无法还原SQL Server中的数据库(单用户)

  •  7
  • user281693  · 技术社区  · 15 年前

    我正在尝试还原我的SQL Server 2005 Express版本中的数据库。我知道,要还原数据库,我需要将其设置为单用户。我给这个命令让它成为一个用户

    USE [master]
    ALTER DATABASE database_name SET SINGLE_USER WITH ROLLBACK IMMEDIATE
    

    这个命令执行正确,我甚至可以在这个数据库的对象资源管理器中看到一个小图像,显示这个用户现在是单个用户。

    现在,我尝试通过以下步骤还原数据库 ->右键单击数据库和任务,然后还原数据库。我正在选择备份文件所在的路径并单击还原。

    但我还是得到了这个错误:“由于数据库正在使用(microsoft.sqlserver.smo),无法获得独占访问。”我错过了什么吗?我在谷歌上搜索过,所有的网站都建议数据库应该是单用户模式,而不是其他模式。

    我没有尝试分离和附加数据库方法。我以前从未这样做过,我想知道这样做是否安全。

    编辑:谢谢你的回答。两人都给了我相同的答案,所以我选择了一个答案。

    我甚至从选项中选择了覆盖现有数据库。

    3 回复  |  直到 13 年前
        1
  •  4
  •   momo    13 年前

    首先,最好是备份和恢复,而不是分离和附加。

    其次,最有可能的情况是,您用来设置数据库的会话 SINGLE_USER 当您尝试运行恢复时仍然拥有它(因为您使用的是GUI,所以它在自己的会话下连接,所以无法访问)。

    要么执行文本还原命令,要么切换查询窗口以先使用另一个数据库,如master。或者您可以关闭查询窗口,使其不再连接。

    您可以随时检查与谁有联系 select * from master.dbo.sysprocesses .

    更新

    假设要还原的数据库已经存在,并且如果磁盘上只有一个备份文件(其中没有多个备份),并且在还原完整备份后不需要还原日志文件,那么通过脚本还原是超级、超级简单的:

    RESTORE DATABASE DBName FROM DISK = 'C:\path\DBNameBackup.bak';
    

    学习此语法将使您的生活更轻松,因为当您设置单用户时,您已经处于连接的唯一会话中。另外,我发现键入restore命令比使用GUI要快,我喜欢对事物的控制。重复这一点最终会巩固你的思想,你不必再去查语法了。

    恢复日志文件甚至不那么困难。只需记住一件简单的事情, WITH NORECOVERY :

    RESTORE DATABASE DBName FROM DISK = 'C:\path\DBNameBackup.bak' WITH NORECOVERY;
    RESTORE LOG DBName FROM DISK = 'C:\path\DBNameBackup1.log' WITH NORECOVERY;
    RESTORE LOG DBName FROM DISK = 'C:\path\DBNameBackup2.log' WITH NORECOVERY;
    RESTORE LOG DBName FROM DISK = 'C:\path\DBNameBackup3.log' WITH NORECOVERY;
    ... 4 5 6 7 and so on
    RESTORE LOG DBName FROM DISK = 'C:\path\DBNameBackupX.log' WITH RECOVERY;
    

    那里…您已经很容易地恢复了日志文件。您甚至可以使用 WITH STOPAT !另外,如果您忘记并意外地提交了最后一条日志还原语句 与诺克利夫 那你就发吧 RESTORE DATABASE DBName WITH RECOVERY; 执行使数据库可用的最后步骤(回滚未提交的事务等)。

        2
  •  2
  •   Bat_Programmer    14 年前

    可以使用此脚本终止使用数据库的所有进程,然后再次尝试还原它:

    declare @sql as varchar(20), @spid as int
    select @spid = min(spid)  from master..sysprocesses  where dbid = db_id('<database_name>') 
    and spid != @@spid    
    
    while (@spid is not null)
    begin
        print 'Killing process ' + cast(@spid as varchar) + ' ...'
        set @sql = 'kill ' + cast(@spid as varchar)
        exec (@sql)
    
        select 
            @spid = min(spid)  
        from 
            master..sysprocesses  
        where 
            dbid = db_id('<database_name>') 
            and spid != @@spid
    end 
    
    print 'Process completed...'
    
        3
  •  1
  •   mevdiven    15 年前
    • 转到左侧列表中“常规”下的“选项”项。
    • 确保选中“覆盖现有数据库”(“还原选项”部分)。

    祝你好运。