我有 SQL Server 2017。那里有一个 3 TB 大小的数据库。不知何故,由于长时间运行的事务,数据库在 SQL 服务器重新启动后陷入了“恢复”模式。当我检查 sql 错误日志时,它说剩余 2 189 255 秒(第 2 阶段,共 3 阶段)已完成,将近 25 天。我的目标是即使丢失了一些数据,也能使数据库联机。
所以我运行了下面的命令,但没有运气。
USE [master]
GO
RESTORE DATABASE test WITH RECOVERY
--Msg 3101, Level 16, State 1, Line 6
--Exclusive access could not be obtained because the database is in use.
--Msg 3013, Level 16, State 1, Line 6
--RESTORE DATABASE is terminating abnormally.
ALTER DATABASE test SET EMERGENCY;
GO
--Msg 5011, Level 14, State 7, Line 13
--User does not have permission to alter database 'DragonDriveConnect',
the database does not exist, or the database is not in a state that
allows access checks.
--Msg 5069, Level 16, State 1, Line 13
--ALTER DATABASE statement failed.
DBCC CHECKDB (DragonDriveConnect, REPAIR_ALLOW_DATA_LOSS) WITH
ALL_ERRORMSGS;
GO
--Msg 922, Level 14, State 1, Line 22
--Database 'DragonDriveConnect' is being recovered. Waiting until
recovery is finished.
Run Code Online (Sandbox Code Playgroud)
最后,我也尝试删除数据库,但这也不起作用,并给我错误说无法删除。
我该如何摆脱这种局面?
AMt*_*two 10
您在 SQL Server 错误日志中看到的错误是这样的:
数据库 'CrashTestDummy' (9) 的恢复已完成 0%(剩余大约 42 秒)。第 2 阶段,共 3 阶段。这只是一条信息性消息。无需用户操作
更笼统地说,它会说:
数据库 '
{Database Name}' ({Database ID}) 的恢复已{N}完成 %(大约{N}还剩几秒)。第{N}3阶段。这只是一条信息性消息。无需用户操作
因为您的数据库在重新启动时没有完全关闭,所以数据库必须经过“崩溃恢复”。这是确保数据库保持一致所必需的。当数据库没有完全关闭时,SQL Server 必须确保写入事务日志的事务已与数据文件正确协调。
保证所有事务都写入事务日志。但是,更新数据最初仅在内存中完成。对物理数据文件的更新是通过检查点异步完成的。数据文件更新的异步特性是崩溃或不正常关机需要在启动时进行额外工作的原因。
如错误消息所示,恢复分为三个阶段。这些中的每一个本质上都是通过事务日志:
这个阶段只是审查事务日志并确定需要做什么。它将确定最近的检查点是什么时候,以及可能需要前滚或后滚哪些事务以确保一致性。
需要查看事务日志中已完成的事务,以确保数据文件已完成更新。否则,仅在内存中的更改可能会丢失。
此阶段将获取在最近检查点之后提交的那些事务并重做它们,以确保它们被持久化到数据文件中。
如果您使用的是 SQL Server 企业版,快速恢复将允许数据库在此恢复阶段后联机并可用。如果您使用的不是企业版,则在撤消阶段完成之前,数据库将不可用。
事务日志中已回滚或在“崩溃”时未提交的事务必须回滚。SQL Server 必须验证是否对数据文件进行了未提交的更改,这些更改已被撤消。如果没有这个,回滚的更改可能会被部分提交,违反数据库的ACID 原则。
此阶段将执行崩溃时未提交或在最终检查点后回滚的任何事务的回滚。
当数据库处于恢复状态时,尝试通过这样的RESTORE命令使数据库联机将失败:
RESTORE DATABASE CrashTestDummy WITH RECOVERY;
Run Code Online (Sandbox Code Playgroud)
SQL Server已经在尝试这样做。该RESTORE...WITH RECOVERY;会简单地把数据库通过完全相同的步骤,以一致的方式使数据库联机。
正确的做法是耐心等待。错误日志中的这一部分消息是您应该注意的:
无需用户操作
另请注意,剩余时间是估计值。根据我的经验,这是非常不准确的。有时剩余的时间会变大,而不是减少。有时候会报完成时间很长,突然就完成的很快。它只是一个估计。
我建议不要这样做。我建议您永远不要使用生产数据库执行此操作。有一个过程可以在没有事务日志的情况下附加数据库,并要求 SQL Server 将ATTACH_REBUILD_LOG. 我不会详细说明所有步骤,但该过程的“重点”是这样做:
CREATE DATABASE CrashTestDummy
ON (FILENAME = 'C:\SQL\MSSQL15.MSSQLSERVER\MSSQL\DATA\CrashTestDummy.mdf')
FOR ATTACH_REBUILD_LOG;
Run Code Online (Sandbox Code Playgroud)
在崩溃的数据库上运行它可能会导致此错误:
无法重建日志,因为在数据库关闭时有打开的事务/用户,数据库没有发生检查点,或者数据库是只读的。如果由于硬件或环境故障手动删除或丢失事务日志文件,则可能会发生此错误。消息 1813,级别 16,状态 2,第 5 行无法打开新数据库“CrashTestDummy”。CREATE DATABASE 已中止。
在这种情况下,你被卡住了。您需要使用原始事务日志并耐心等待。只能等它恢复了。