错误-由于正在使用数据库,因此无法获得独占访问


117

我实际上正在尝试制作一个脚本(在Sql Server 2008中),以从一个备份文件还原一个数据库。我做了以下代码,但出现错误-

Msg 3101, Level 16, State 1, Line 3
Exclusive access could not be obtained because 
the database is in use.
Msg 3013, Level 16, State 1, Line 3
RESTORE DATABASE is terminating abnormally.

我该如何解决这个问题?

IF DB_ID('AdventureWorksDW') IS NOT NULL 
BEGIN 
RESTORE DATABASE [AdventureWorksDW] 
FILE = N'AdventureWorksDW_Data' 
FROM  
DISK = N'C:\Program Files\Microsoft SQL Server\
MSSQL10_50.SS2008\MSSQL\Backup\AdventureWorksDW.bak' 
WITH  FILE = 1, 
MOVE N'AdventureWorksDW_Data' 
TO N'C:\Program Files\Microsoft SQL Server\
MSSQL10_50.SS2008\MSSQL\DATA\AdventureWorksDW.mdf', 
MOVE N'AdventureWorksDW_Log'  
TO N'C:\Program Files\Microsoft SQL Server\
MSSQL10_50.SS2008\MSSQL\DATA\AdventureWorksDW_0.LDF', 
NOUNLOAD,  STATS = 10 
END

如果我可以使它正常工作,也许我可以制作一个可靠的脚本来从一个文件夹中还原多个数据库。我在网上找不到任何可靠的代码。我的代码可能是可靠的,因为它是由SS本身生成的。
Steam

Answers:


104

我假设,如果要还原数据库,则无需关心该数据库上的任何现有事务。对?如果是这样,这应该为您工作:

USE master
GO

ALTER DATABASE AdventureWorksDW
SET SINGLE_USER
--This rolls back all uncommitted transactions in the db.
WITH ROLLBACK IMMEDIATE
GO

RESTORE DATABASE AdventureWorksDW
FROM ...
...
GO

现在,要注意另外一项。将数据库设置为单用户模式后,其他人可能会尝试连接到该数据库。如果它们成功,您将无法继续进行还原。这是一场比赛!我的建议是一次运行所有三个语句。


事务中的所有三个语句。
Steam

1
每当我尝试访问该Adventureworks数据库时,我的SSMS都会进入无响应模式。
2014年

2
实际上USE master,他的意思不是USER master
2015年

7
只需添加ALTER DATABASE [AdventureWorksDW] SET MULTI_USER末尾以确保数据库恢复为正常的多用户模式。
gnaanaa

1
@gnaanaa:如果备份的数据库SINGLE_USER在备份时处于模式,则在SINGLE_USER还原备份时它将处于模式。如果MULTI_USER在备份时处于MULTI_USER模式,则在还原时将处于模式。您提出了一个很好的观点:还原完成后绝对值得检查。您还可以在备份媒体上运行RESTORE HEADERONLY,然后IsSingleUser在该Flags列上进行检查或按位进行数学运算。
戴夫·梅森

234
  1. 设置还原文件的路径。
  2. 点击左侧的“选项”。
  3. 取消选中“还原前进行尾日志备份”
  4. 选中复选框-“关闭与目标数据库的现有连接”。 在此处输入图片说明
  5. 单击确定。

16
就我而言,该复选框为灰色。但是,我重新开始,能够在选择要还原的源之前选中此框。选择备份文件后,该选项再次变灰,但仍选中该框,还原工作正常。
phansen

3
为我免于键入SQL的荣誉。所有答案中唯一的GUI方法。
莱昂内·陈

我希望这会像其他人一样为我工作。但是对我而言,此复选框始终为灰色。以下是Andrei Karchueuski的 回答,对我有用
Devraj Gadhavi '18

11
在还原之前,我还必须取消选中“还原前先进行尾日志备份”。
Hylle

3
“还原前进行尾日志备份”也需要取消选中。谢谢
jedu

50

在还原数据库之前执行以下查询:

alter database [YourDBName] 
set offline with rollback immediate

恢复后的这个:

  alter database [YourDBName] 
  set online

在试验应用程序连接击败了我的查询的还原和随后的MULTI_USER调用之后,我最终通过SINGLE_USER切换到此方法。还原无法获得独占访问,并且旧数据库仍处于SINGLE_USER模式。
自助餐

3
这对我有用。恢复后,它将自动联机。
Dileep

3
这有效,并且避免了已接受答案中的竞争条件。
Scott Whitlock

1
谢谢你安德烈。
埃尔多安

11

对我来说,解决方案是:

  1. 在左侧的选项卡中,选中覆盖现有数据库(替换)。

  2. 取消选中所有其他选项。

  3. 选择源数据库和目标数据库。

  4. 单击确定。

而已。


1
也为我工作。我还必须取消选中“还原前先进行尾日志备份”。
尤瓦

7

在还原数据库之前,使用以下脚本查找并杀死所有打开的数据库连接。

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

我认为您只需要在尝试还原之前将数据库设置为单用户模式,如下所示,只需确保您使用的是 master

USE master
GO
ALTER DATABASE AdventureWorksDW
SET SINGLE_USER

2

我刚刚重新启动了sqlexpress服务,然后还原完成正常


我能说点什么...对我来说很奏效!
BabaNew

1
OP的还原脚本有问题,因为他没有考虑到他的数据库可能已经被使用的事实。解决方案是使用适当的命令更新他的脚本,以允许他独占访问数据库。重新启动服务可能对您有用,但这不是解决他的问题的适当方法。
PL

1
Use Master
alter database databasename set offline with rollback immediate;

--Do Actual Restore
RESTORE DATABASE databasename
FROM DISK = 'path of bak file'
WITH MOVE 'datafile_data' TO 'D:\newDATA\data.mdf',
MOVE 'logfile_Log' TO 'D:\newDATA\DATA_log.ldf',replace

alter database databasename set online with rollback immediate;
GO

1

解决方案1:重新启动SQL服务并尝试还原数据库解决方案2:重新启动系统/服务器并尝试还原数据库解决方案3:取回当前数据库,删除当前/目标数据库,然后尝试还原数据库。


1

将数据库设置为单用户模式对我而言不起作用,但是将其脱机然后又使其重新联机确实可行。在“任务”下的数据库的右键菜单中。

确保选中对话框中的“删除所有活动连接”选项。


0

这是我将数据库从生产还原到开发的一种方式:

注意:我正在通过SSAS作业来将生产数据库每天推送到开发中:

步骤1:删除开发中的前一天备份:

declare @sql varchar(1024);

set @sql = 'DEL C:\ProdAEandAEXdataBACKUP\AE11.bak'
exec master..xp_cmdshell @sql

步骤2:将生产数据库复制到开发中:

declare @cmdstring varchar(1000)
set @cmdstring = 'copy \\Share\SQLDBBackup\AE11.bak C:\ProdAEandAEXdataBACKUP'
exec master..xp_cmdshell @cmdstring 

步骤3:通过运行.sql脚本进行还原

SQLCMD -E -S dev-erpdata1 -b -i "C:\ProdAEandAEXdataBACKUP\AE11_Restore.sql"

AE11_Restore.sql文件中的代码:

RESTORE DATABASE AE11
FROM DISK = N'C:\ProdAEandAEXdataBACKUP\AE11.bak'
WITH MOVE 'AE11' TO 'E:\SQL_DATA\AE11.mdf',
MOVE 'AE11_log' TO 'D:\SQL_LOGS\AE11.ldf',
RECOVERY;

0

没有足够的磁盘空间还原Db时出现此错误。清理一些空间可以解决它。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.