“数据库正在转换”错误


12

今天,我正在尝试通过现有数据库还原数据库,我只是在SSMS中右键单击该数据库->任务->脱机,以便可以还原该数据库。

一个小弹出窗口出现并显示Query Executing.....了一段时间,然后抛出了一个错误说Database is in use cannot take it offline。我从中收集到该数据库的一些活动连接,因此我尝试执行以下查询

USE master
GO
ALTER DATABASE My_DatabaseName
SET OFFLINE WITH ROLLBACK IMMEDIATE
GO

SSMS此时再次显示Query Executing.....一段时间,然后引发以下错误:

Msg 5061, Level 16, State 1, Line 1
ALTER DATABASE failed because a lock could not be placed on database 'My_DatabaseName'. Try again later.
Msg 5069, Level 16, State 1, Line 1
ALTER DATABASE statement failed.

此后,我无法通过SSMS连接到数据库。当我尝试使用SSMS将其脱机时,它抛出一条错误消息:

Database is in Transition. Try later .....

这时我根本无法触及任何我尝试返回相同错误信息的数据库Database is in Transition

我在Google上阅读了一些人们遇到过类似问题的问题,他们建议关闭SSMS,然后再次打开它,我也是。由于这只是一个开发服务器,因此我只是使用SSMS删除了数据库并恢复了新数据库。

我的问题是可能是什么原因造成的?以及如何避免将来发生这种情况,并且如果将来在相同的情况下遇到问题,是否还有其他方法可以解决此问题,然后删除整个数据库?

谢谢

Answers:


24

复制

  1. 打开SSMS
  2. 在新的查询窗口中输入以下内容

    use <YourDatabase>;
    go
    
  3. 转到对象资源管理器(SSMS),然后右键单击<YourDatabase>-> Tasks->Take Offline
  4. 打开第二个新查询窗口,然后键入以下内容:

    use <YourDatabase>;
    go
    

将提示您以下消息:

消息952,级别16,状态1,第1行
数据库“ TestDb1”正在转换中。稍后尝试声明。

发生这种情况的原因可以从与以下查询类似的诊断查询中找到:

select
    l.resource_type,
    l.request_mode,
    l.request_status,
    l.request_session_id,
    r.command,
    r.status,
    r.blocking_session_id,
    r.wait_type,
    r.wait_time,
    r.wait_resource,
    request_sql_text = st.text,
    s.program_name,
    most_recent_sql_text = stc.text
from sys.dm_tran_locks l
left join sys.dm_exec_requests r
on l.request_session_id = r.session_id
left join sys.dm_exec_sessions s
on l.request_session_id = s.session_id
left join sys.dm_exec_connections c
on s.session_id = c.session_id
outer apply sys.dm_exec_sql_text(r.sql_handle) st
outer apply sys.dm_exec_sql_text(c.most_recent_sql_handle) stc
where l.resource_database_id = db_id('<YourDatabase>')
order by request_session_id;

对于它的价值,您不需要对象资源管理器即可重现此错误。您只需要尝试相同操作的阻止请求(在这种情况下,使数据库脱机)。有关T-SQL中的三个步骤,请参见下面的屏幕截图:

在此处输入图片说明

您最有可能看到的是您的Object Explorer会话被另一个会话阻止(显示为blocking_session_id)。该对象资源管理器会话将尝试获取X数据库的排他锁()。在上述repro的情况下,对象资源管理器会话被授予了更新锁(U),并尝试转换为互斥锁(X)。它的wait_type为LCK_M_X,被我们的会话阻止,该会话由第一个查询窗口表示(获取数据库上的use <YourDatabase>共享锁(S))。

然后,此错误来自另一个试图获取锁的会话,并且此错误消息导致拒绝会话以获取对尝试转换为其他状态(在这种情况下为在线状态)的数据库的访问到离线过渡)。

下次您该怎么办?

首先,不要惊慌也不要开始删除数据库。您需要采取故障排除方法(与上面的诊断查询类似),以查明为什么看到了自己看到的东西。收到类似这样的消息,或者当出现“挂起”消息时,您应该自动假定并发性不足并开始深入研究阻塞(这sys.dm_tran_locks是一个不错的开始)。

另外,我确实相信您最好在采取任何随机措施之前先找出问题的根源。不仅通过此操作,而且还适用于所有意外行为。知道是什么真正导致了您的问题,很明显这没什么大不了的。您基本上有一个阻塞链,并且父阻塞程序很可能刚刚发出了KILLon,或者如果会话的请求是您不希望的,KILL那么您可以等到它完成为止。无论哪种方式,您都具有在特定情况下(回滚或等待提交)做出正确而谨慎决定的知识。

另一件事值得注意,这就是为什么我总是选择T-SQL替代而不是GUI的原因之一。您确切地知道您正在使用T-SQL执行什么以及SQL Server在做什么。毕竟,您发出了明确的命令。当您使用GUI时,实际的T-SQL将成为一种抽象。在这种情况下,我查看了受阻的对象资源管理器试图使数据库脱机,事实是ALTER DATABASE <YourDatabase> SET OFFLINE。没有回滚的尝试,这就是它无限期等待的原因。在您的情况下,如果您要回滚在该数据库上已锁定的会话,那么,ALTER DATABASE ... SET OFFLINE WITH ROLLBACK IMMEDIATE如果您最初确定回滚是可以的,则很可能已经足够了。



0

无需执行任何操作,只需SqLWB.exe从任务管理器中终止该进程,打开SQL Server,右键单击数据库并将其脱机。如果不起作用,则在终止会话后,键入命令

ALTER DATABASE [Test4] SET OFFLINE WITH ROLLBACK IMMEDIATE

然后离线。它会像对我一样起作用。

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.