ChatGPT解决这个技术问题 Extra ChatGPT

SQL-Server: 错误 - 无法获得独占访问权限,因为数据库正在使用中

我实际上是在尝试制作一个脚本(在 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 本身生成的。

a
avs099

设置恢复文件的路径。点击左侧的“选项”。取消选中“还原前进行尾日志备份”勾选复选框 - “关闭与目标数据库的现有连接”。单击确定。


在我的情况下,该复选框是灰色的。但是,我重新开始并能够在选择要恢复的源之前选中该框。选择备份文件后,该选项再次变灰,但该框仍被选中并且恢复工作。
感谢您让我免于输入 SQL。所有答案中唯一的 GUI 方法。
在我能够恢复之前,我还必须取消选中“在恢复之前进行尾日志备份”。
“在还原之前进行尾日志备份”这也需要取消选中。谢谢
在我选择要恢复的文件之前,我转到选项并选择关闭所有现有连接。之后,我选择了要恢复的文件。这种方式对我有用。
D
Dave Mason

我假设如果您要恢复数据库,则不关心该数据库上的任何现有事务。正确的?如果是这样,这应该适合你:

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

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


事务中的所有三个语句。
每当我尝试访问 Adventureworks 数据库时,我的 SSMS 都会进入无响应模式。
他实际上是指USE master,而不是USER master
只需在末尾添加 ALTER DATABASE [AdventureWorksDW] SET MULTI_USER 以确保数据库回到正常的多用户模式。
@gnaanaa:如果备份数据库在备份时处于 SINGLE_USER 模式,则在恢复备份时它将处于 SINGLE_USER 模式。如果它在备份时处于 MULTI_USER 模式,则在恢复时它将处于 MULTI_USER 模式。您提出了一个很好的观点:还原完成后绝对值得检查。您还可以在备份媒体上运行 RESTORE HEADERONLY 并检查 IsSingleUser 或对 Flags 列进行逐位数学运算。
A
Andrei Karcheuski

在恢复数据库之前执行此查询:

alter database [YourDBName] 
set offline with rollback immediate

恢复后的这个:

  alter database [YourDBName] 
  set online

在试点应用程序连接击败我的查询的恢复和随后的 MULTI_USER 调用后,我最终通过 SINGLE_USER 切换到此方法。恢复未能获得独占访问权限,旧数据库处于 SINGLE_USER 模式。
这对我有用。恢复后它会自动联机。
这有效,并且避免了接受答案中的竞争条件。
谢谢安德烈。
P
Pang

对我来说,解决方案是:

在左侧的 optoins 选项卡中选中覆盖现有数据库(WITH REPLACE)。取消选中所有其他选项。选择源和目标数据库。单击确定。

而已。


也为我工作。我还必须取消选中“在还原之前进行尾日志备份”。
A
Aqeel Haider

在恢复数据库之前,使用以下脚本查找并终止所有打开的数据库连接。

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...'

希望这会有所帮助...


A
Ali Karaca

将原始数据库离线为我工作

https://i.stack.imgur.com/eRrwO.png


这对我也适用于 mgmt studio 2018/2019
B
BabaNew

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


关于downvote我能说什么......对我来说它有效!
OP 的恢复脚本有问题,因为他没有考虑到他的数据库可能已经在使用中的事实。解决方案是使用适当的命令更新他的脚本,允许他独占访问数据库。虽然重新启动服务可能对您有用,但这不是解决他的问题的合适方法。
对我来说(从字面上看)上面的所有解决方案都不起作用,只有这个起作用。
J
Jason

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

USE master
GO
ALTER DATABASE AdventureWorksDW
SET SINGLE_USER

A
Amit Joshi
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

J
Jeffrey Harmon

将数据库设置为单用户模式对我不起作用,但将其脱机,然后将其重新联机确实有效。它位于数据库的右键菜单中,位于任务下。

请务必选中对话框中的“删除所有活动连接”选项。


P
Promise Preston

我在尝试恢复 MS SQL Server 2012 上的数据库时遇到了这个问题。

这对我有用:

我必须首先在备份文件上运行 RESTORE FILELISTONLY 命令以列出逻辑文件名:

RESTORE FILELISTONLY 
    FROM DISK = 'C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\Backup\my_db_backup.bak'

这分别显示了数据库的数据和日志文件的逻辑名称和相应的物理名称:

LogicalName      PhysicalName               
com.my_db        C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\DATA\com.my_db.mdf
com.my_db_log    C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\DATA\com.my_db_log.ldf

我所要做的就是在我的数据库还原脚本中分别替换数据库的数据和日志文件的 LogicalName 和相应的 PhysicalName:

USE master;
GO

ALTER DATABASE my_db SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
GO

    
RESTORE DATABASE my_db
    FROM DISK = 'C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\Backup\my_db_backup.bak'
    WITH REPLACE,
    MOVE 'com.my_db' TO 'C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\DATA\com.my_db.mdf',
    MOVE 'com.my_db_log' TO 'C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\DATA\com.my_db_log.ldf'
GO
    
ALTER DATABASE my_db SET MULTI_USER;
GO

并且数据库还原任务成功运行:

就这样。

我希望这有帮助


N
NonProgrammer

这是我从生产到开发进行数据库恢复的一种方式:

注意:我通过 SSAS 工作每天将生产数据库推向开发:

Step1:删除开发中的前一天备份:

declare @sql varchar(1024);

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

Step2:将生产数据库复制到开发:

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

Step3:通过运行.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;

u
user3790083

当没有足够的磁盘空间来恢复 Db 时出现此错误。清理一些空间解决了它。


J
Joseph Joy

解决方案 1:重新启动 SQL 服务并尝试恢复 DB 解决方案 2:重新启动系统/服务器并尝试恢复 DB 解决方案 3:收回当前 DB,删除当前/目标 DB 并尝试恢复 DB。


服务器上可能有其他不需要停止的数据库。
d
derek morrison

当我不知道时,我收到了这个错误,其他人在另一个 SSMS 会话中连接到数据库。在我将它们注销后,还原成功完成。