LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

SQL Server 恢复挂起解决方案

admin
2024年8月24日 0:9 本文热度 107

在数据库的日常管理中,我们不可避免的会遇到,服务器突然断电(没有进行电源冗余),服务器崩溃或者 SQL Server 服务突然停掉,悲催的是日志文件也损毁了,SQL Server服务器起来之后,发现数据库处于“恢复挂起”模式;更悲哀的是该数据库没有备份或者备份已经比较久远;最最可悲的是,已经做好了丢失部分数据的准备,使用 DBCC CEHECKDB 的 REPAIR_ALLOW_DATA_LOSS 选项修复数据库后,数据库还是无法上线:

文件激活失败。物理文件名称'D:\data\archlog1.ldf'可能不正确。

无法重新生成日志,原因是数据库关闭时存在打开的事务/用户,该数据库没有检查点或者该数据库是只读的。如果事务日志文件被手动删除或者由于硬件或环境问题而丢失,则可能出现此错误。

消息 1813,级别 16,状态 2,第 18 行

无法打开新数据库 'PerfStats'。CREATE DATABASE 中止。

本文将分享两种处理这种问题的方式,帮助您成功恢复数据库。

模拟环境

--窗口1USE PerfStatsGO

SELECT * INTO testObject FROM sys.all_objects
--前面脚本执行完成再执行该插入语句INSERT INTO dbo.testObjectSELECT o.* FROM sys.all_objects o CROSS JOIN sys.all_objects o1 CROSS JOIN sys.all_objects o2 CROSS JOIN sys.all_objects o3

首先,在数据库 PerfStats 中创建 testObject 表,并插入所有对象数据。接下来我们运行插入脚本,使用多次 CROSS JOIN,以获得足够多的数据,赢得时间,让我们在关闭测试实例时,插入事务仍然在运行。这将使得数据库处于不一致状态,需要在数据库启动时,执行恢复。在另外一个 SSMS 窗口执行如下关闭 SQL Server 实例的脚本:

--窗口2SHUTDOWN WITH NOWAIT

停服后,将PerfStats 的日志文件改名或者移到其他路径,重新启动SQL Server 服务,可以看到,PerfStats 数据库处于“恢复挂起”状态:

此时,我们仅有一个孤立的,不一致的数据库文件。

首先,让我们通过删除数据库来清除系统分类。此时,我们必须先离线数据库:

USE masterGO
ALTER DATABASE Archive SET OFFLINE;

copy或者重命名数据文件,以备我们测试使用。然后通过删除数据库,来清除系统分类:

DROP DATABASE PerfStats

使用 ATTACH_REBUILD_LOG 来重建日志文件:

USE masterGOCREATE DATABASE PerfStats ON(FILENAME='D:\db\PerfStats.mdf')FOR ATTACH_REBUILD_LOGGO

文件激活失败。物理文件名称'D:\DB\PerfStats_log.ldf'可能不正确。

无法重新生成日志,原因是数据库关闭时存在打开的事务/用户,该数据库没有检查点或者该数据库是只读的。如果事务日志文件被手动删除或者由于硬件或环境问题而丢失,则可能出现此错误。

消息 1813,级别 16,状态 2,第 7 行

无法打开新数据库 'PerfStats'。CREATE DATABASE 中止。

到此为止,我们很可能只有去找备份文件还原了(如果有的话),否则可能就是一场大灾难了。

本文接下来将介绍两种可以用来恢复数据库的方式,以帮助您度过劫难。第一种方式是使用 CREATE DATABASE 语句中非归档的的命令。如你所知,微软是不支持使用非归档的语句,因为使用这个语句一旦出了问题,他们是概不负责的。另一种方法更机智,不需要使用非归档功能。

方案一、未归档的ATTACH_FORCE_REBUILD_LOG命令

到目前为止,因为没有日志文件,我们使用 CREATE DATABASE…FOR ATTACH 语句恢复数据库会失败。同时,因为数据库中有打开的事务,我们也不能使用 ATTACH_REBUILD_LOG 命令。有一个未归档的命令 ATTACH_FORCE_REBUILD_LOG 命令,正如其名称所显示,强制 CREATE DATABASE…FOR ATTACH 语句恢复数据库,尽管其是孤立的、有打开事务的数据库。当然,也会创建一个新日志文件。

USE masterGO
CREATE DATABASE PerfStats ON(FILENAME='D:\db\PerfStats.mdf')FOR ATTACH_FORCE_REBUILD_LOGGO

数据库虽然恢复正常,但数据表对象仍然无效:

使用最小数据丢失的方式,修复数据库:

USE PerfStatsGO
ALTER DATABASE PerfStats SET SINGLE_USER WITH NO_WAITGO
DBCC CHECKDB(PerfStats,REPAIR_REBUILD) WITH ALL_ERRORMSGSGO

看到,有380个一致性错误,仅仅修复两个。

USE PerfStatsGO ALTER DATABASE PerfStats_Repair SET EMERGENCYGO
ALTER DATABASE PerfStats SET SINGLE_USER WITH NO_WAITGO

DBCC CHECKDB(PerfStats,REPAIR_ALLOW_DATA_LOSS) WITH ALL_ERRORMSGS

最后虽然修复好了数据库,但数据库最后一次checkpoint点之后的所有数据将会丢失。


方案二、不使用未归档的功能附加损毁的SQL Server数据库

步骤一、创建新数据库

USE masterGO
CREATE DATABASE PerfStats_RepairCONTAINMENT=NONEON PRIMARY(NAME='PerfStats_Repair' ,FILENAME=N'D:\DB\PerfStats_Repair.mdf' ,SIZE=8MB ,MAXSIZE=UNLIMITED ,FILEGROWTH=64MB)LOG ON(NAME=N'PerfStats_Repair_log' ,FILENAME=N'D:\DB\PerfStats_Repair_log.ldf' ,SIZE=8MB ,MAXSIZE=20GB ,FILEGROWTH=32MB)GO

步骤二、离线新数据库

USE masterGOALTER DATABASE PerfStats_Repair SET OFFLINE WITH ROLLBACK IMMEDIATE

步骤三、将新数据库的文件路径指向我们的孤立的?mdf?文件,并且将日志文件指向一个不存在的文件

USE masterGOALTER DATABASE PerfStats_Repair MODIFY FILE(NAME='PerfStats_Repair' ,FILENAME='D:\DB\PerfStats.mdf')ALTER DATABASE PerfStats_Repair MODIFY FILE(NAME='PerfStats_Repair_log' ,FILENAME='D:\DB\PerfStats_log.ldf')GO

测试上线情况:

USE masterGO
ALTER DATABASE PerfStats_Repair SET ONLINE

消息 5120,级别 16,状态 101,第 39 行

无法打开物理文件“D:\DB\PerfStats.mdf”。操作系统错误 5:“5(拒绝访问。)”。

文件激活失败。物理文件名称'D:\DB\PerfStats_log.ldf'可能不正确。

消息 5181,级别 16,状态 5,第 39 行

无法重新启动数据库“PerfStats_Repair”。将恢复到以前的状态。

消息 5069,级别 16,状态 1,第 39 行

ALTER DATABASE 语句失败。

无法打开物理文件“D:\DB\PerfStats.mdf”。操作系统错误 5:“5(拒绝访问。)”。这是因为在移动MDF 文件时,Authenticated Users 的权限改变了,需要为其添加“完全控制”权限,右击文件→属性→点选 Authenticated Users 用户→编辑→点选Authenticated Users→勾选下方“完全控制”右侧“允许”下的多选框→确定即可

重新运行ONLINE 脚本。即使您不是 SQL Server 专家,也能够猜测到,运行那个脚本会报错。但是,如果您看一看下图捕获到的错误信息,您将会发现,当SQL Server 无法找到事务日志文件时(我们之前的操作是改变系统目录,将其指向一个不存在的文件),会对日志文件进行重建。当然,重建日志文件失败,其错误信息和我们附加孤立的 *.mdf 文件相同,此时,和之前附件情况唯一不同的是,*.mdf 文件附加成功了,这离我们成功又进了一步。

文件激活失败。物理文件名称'D:\DB\PerfStats_log.ldf'可能不正确。

无法重新生成日志,原因是数据库关闭时存在打开的事务/用户,该数据库没有检查点或者该数据库是只读的。如果事务日志文件被手动删除或者由于硬件或环境问题而丢失,则可能出现此错误。

消息 5181,级别 16,状态 5,第 39 行

无法重新启动数据库“PerfStats_Repair”。将恢复到以前的状态。

消息 5069,级别 16,状态 1,第 39 行

ALTER DATABASE 语句失败。

此时数据库 PerfStats_repair 数据库处于“恢复还原”状态。

步骤四、重建SQL Server 事务日志文件

现在,您会看到,重建 SQL Server 事务日志并不是非常复杂,但是,您必须接受将要丢失数据这一事实。事实上,只有在从备份恢复损坏的数据库这条路被断掉之后,您才能选择使用这种方式。例如,如果一个事务在更新索引,并且更新操作执行了一个页拆分,你可能丢失之前提交的事务,因为页拆分是要进行日志记录的,而这一记录会因为日志文件的丢失而消失。

下面是恢复数据库的脚本:

USE masterGO
DBCC TRACEON(3604)GO
ALTER DATABASE PerfStats_Repair SET EMERGENCYGO
ALTER DATABASE PerfStats_Repair SET SINGLE_USERGO
DBCC CHECKDB(PerfStats_Repair,REPAIR_ALLOW_DATA_LOSS)GO
ALTER DATABASE PerfStats_Repair SET MULTI_USER

第一个DBCC 命令是将所有的输出展示在查询结果中,而不是记录在错误日志中。接下来两个脚本将数据库分别置于紧急模式和单用户模式,这是我们执行 DBCC CHECKDB 的 REPAIR_ALLOW_DATA_LOSS 选项的前提。最后一句脚本是将数据库恢复多用户模式。

下图框起来的部分说明错误日志已经重建了:

文件激活失败。物理文件名称'D:\DB\PerfStats_log.ldf'可能不正确。

无法重新生成日志,原因是数据库关闭时存在打开的事务/用户,该数据库没有检查点或者该数据库是只读的。如果事务日志文件被手动删除或者由于硬件或环境问题而丢失,则可能出现此错误。

将禁用数据库 "PerfStats_Repair" 中的 Service Broker,因为数据库(316755B8-71DB-41B0-A4C5-1D076DB9EA0E)中的 Service Broker GUID 与 sys.databases (52C1EA48-8B63-446C-95AA-76D65C6DE5C5)中的不匹配。

警告: 数据库 'PerfStats_Repair' 的日志已重新生成。已失去事务的一致性。RESTORE 链已断开,服务器不再有以前的日志文件的上下文,因此您需要了解它们的内容。应运行 DBCC CHECKDB 验证物理一致性。数据库已置于 dbo-only 模式。在准备使数据库可用时,需要重置数据库选项,并删除所有多余的日志文件。

至此,数据库已经恢复完成。

写在最后,完成数据库备份策略必不可少,备份、备份,还是备份!!!


该文章在 2024/8/24 12:09:05 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2025 ClickSun All Rights Reserved