关闭

【SQL Server备份恢复】数据库恢复:对page header的恢复

1123人阅读 评论(1) 收藏 举报
分类:

前两天在论坛,看到有个网友提问,说是:

格式化磁盘前把.mdf和.ldf拷贝出来了,然后格式化完成后在拷贝回去(拷贝前后都没有错误提示,文件大小也一样),在企业管理器中附加数据库出错,提示“错误823”,附加数据库失败。从网上搜了搜方案:重建同名数据库之类的做法都试过了,都不能解决问题。请问版主或各位高手,有什么解决方案吗?
注:拷贝之前数据库使用正常,并且以前都是此种方法附加的,这次不知如何出现这样的问题了。


帮他尝试恢复:

1、他已经按照网上的方法,新建了一个同名的数据库。


2、停止服务,然后把原始的文件拷贝到目录中。


3、启动服务,发现数据库处于质疑状态。


4、运行如下命令,都报错:打不开数据库

dbcc checkdb(xxx);

dbcc checkdb(xxx,repair_allow_data_loss);


5、运行如下命令成功, 设置数据库为紧急模式  

 Use Master  
 GO  
 
 sp_configure 'allow updates', 1  
 reconfigure with override  
 GO  
 
 UPDATE sysdatabases SET status = 32768 where name = 'xxx'  
 GO  

6、再次运行命令,报错:数据库必须处于单用户模式

dbcc checkdb(xxx,repair_allow_data_loss);

7、如果如下命令,设置数据库为单用户模式:

alter database test set single_user

8、再次运行命令,还是报错:数据库必须处于单用户模式

dbcc checkdb(xxx,repair_allow_data_loss);

在这里就觉得很奇怪,明明已经设置为单用户模式了,怎么还报这个错误呢?

在网上找了一下,发现有很多人都有这个问题,但是没有解决办法。


9、尝试运行如下命令,但类似这样的报错:

服务器: 消息 8909,级别 16,状态 1,行 1
表错误: 对象 ID 0,索引 ID 0,页 ID 0。
 服务器: 消息 8966,级别 16,状态 1,行 1
未能读取并闩锁页 (1:123456)(用闩锁类型 SH)。sysobjects 失败。

在网上找到一篇文章:

sql server 系统表损坏修复方法 http://wenku.baidu.com/view/901cd511f18583d04964592e

这个文章中提到的解决方法就是,新建一个数据库,通过dts,把原来数据库的数据,导出到新的数据库中,但前提是其中的表都能访问,也就是能够select * from 表,否则就没用了。


那么有没有什么好的办法,能修复呢?

在网上找了一下,发现有专业的数据恢复公司,能恢复这种错误,从文章中提到的信息来看,应该通过直接构造损坏的页面来修复的。


由于这种情况比较难重现,所以这里模拟当某个数据页的page header损坏时,如何手动修复这个数据页,其实就是一个复制粘帖的过程。


1、先创建一个数据库,创建表,插入数据:

create database w
go

use w
go


if OBJECT_ID('test') is not null
   drop table test

select * into test
from sys.objects
go


insert into test
select * 
from test

2、分离数据库w,把数据文件和日志文件,直接复制到一个备份目录。


3、本来通过dbcc writelog来修改数据,但是应该是没有修改好。

dbcc writepage的语法为:

dbcc writepage 
({ dbid,'dbname' }, fileid, pageid, offset, length, data)


--生成96个字节的数据
select '0x'+replicate('00',96)

dbcc writepage('w',1,310,0,96,
0x000000000000000000000000000000000000000
00000000000000000000000000000000000000000
00000000000000000000000000000000000000000
00000000000000000000000000000000000000000
000000000000000000000000000000)
/*
消息 8939,级别 16,状态 5,第 1 行
表错误: 对象 ID 0,索引 ID -1,分区 ID 0,分配单元 ID 0 (类型为 Unknown),页 (0:0)。测试(m_headerVersion == HEADER_7_0)失败。值为 0 和 1。
消息 8939,级别 16,状态 6,第 1 行
表错误: 对象 ID 0,索引 ID -1,分区 ID 0,分配单元 ID 0 (类型为 Unknown),页 (0:0)。测试((m_type >= DATA_PAGE && m_type <= UNDOFILE_HEADER_PAGE) || (m_type == UNKNOWN_PAGE && level == BASIC_HEADER))失败。值为 0 和 0。
消息 8939,级别 16,状态 7,第 1 行
表错误: 对象 ID 0,索引 ID -1,分区 ID 0,分配单元 ID 0 (类型为 Unknown),页 (0:0)。测试(m_freeData >= PageHeaderOverhead () && m_freeData <= (UINT)PAGESIZE - m_slotCnt * sizeof (Slot))失败。值为 0 和 8192。
DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。
*/

所以,改用二进制编辑工具,输入:0x0026C000,定位到这个物理偏移,然后修改了数据库w中的fileID为1,pageID为310的,前96个字节全为00,这个正好是page header部分:

select 8*1024*310 as '310页在文件中的物理偏移',
       CAST(8*1024*310 as varbinary)  '转化为16进制'
/*
310页在文件中的物理偏移	转化为16进制
2539520	0x0026C000
*/






4、重新附加这个数据库

dbcc checkdb(w)
/*
消息 8909,级别 16,状态 1,第 1 行
表错误: 对象 ID 0,索引 ID -1,分区 ID 0,分配单元 ID 0 (类型为 Unknown),页 ID (1:310) 在其页头中包含错误的页 ID。页头中的 PageId = (0:0)。
CHECKDB 发现有 0 个分配错误和 1 个一致性错误与任何单个的对象都没有关联。

消息 8928,级别 16,状态 1,第 1 行
对象 ID 981578535,索引 ID 0,分区 ID 72057594038910976,分配单元 ID 72057594042580992 (类型为 In-row data): 无法处理页 (1:310)。有关详细信息,请参阅其他错误消息。

CHECKDB 在数据库 'w' 中发现 0 个分配错误和 2 个一致性错误。
对于由 DBCC CHECKDB (w)发现的错误,repair_allow_data_loss 是最低的修复级别。
DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。
*/

5、把数据库分离,从备份的文件中,复制page header到这个文件



6、再次附加数据库,就可以查询了。

不过,使用repair_allow_data_loss也可以恢复。


0
0
查看评论

SQLserver数据备份与恢复

先前做了数据库的备份程序,现在要做一个恢复功能,这样,每天生成备份后,恢复到备份机器上。可以随便检测。   四、数据恢复 1、Restore vs. Recovery Restore和Recovery是两个不同的概念,但在数据恢复过程中又是紧密联系的。 Restore...
  • aasmfox
  • aasmfox
  • 2012-10-31 17:39
  • 2480

SQLSERVER 数据库恢复挂起的解决办法

如果你的数据库还处于挂起状态,请把我下面代码的test改为你的库名,然后执行完,刷新就正常了: USE master GO ALTER DATABASE test SET SINGLE_USER GO ALTER DATABASE test SET EMERGENCY GO DBCC ...
  • zxr85
  • zxr85
  • 2016-07-18 16:22
  • 12129

sql server 出现数据库恢复挂起时 解决办法

alter database sunrise4  set online
  • JackChuFengZhi
  • JackChuFengZhi
  • 2014-06-04 16:15
  • 2611

关于SQLserver2016数据库处于恢复挂起状态的解决方案

由于修改了SQLserver中数据库的默认存储位置,此外还把已有数据库位置改变了,所有出现恢复挂起状态,那么这种情况怎么解决呢?请看下面喽------ 默认位置的查看:右键点击你想要查看的数据库---->属性----->文件    路径即为默认路径 默认路...
  • fsq0827
  • fsq0827
  • 2017-11-10 16:55
  • 266

SQL数据库(7)——数据库恢复技术

事务的基本概念事务的定义 一个数据库操作序列 一个不可分割的工作单位 恢复和并发控制的基本单位 在关系数据库中,一个事务可以使一条或多条SQL语句,或这个程序 事务的特性事务的ACID特性: 原子性 一致性 隔离性 持续性 原子性事务是数据库的逻辑工作单位 事务中包括的诸多操作要么都做,要么都...
  • longxinghaofeng
  • longxinghaofeng
  • 2017-01-01 13:26
  • 1108

DB2 数据库在线备份和恢复的操作步骤

1、数据库在线备份操作命令如下: DB2 backup db 数据库名 online to 备份路径 例如:db2 backup db tony online to /home/db2inst/db2backup 2、数据库恢复操作命令如下: ...
  • tony7706
  • tony7706
  • 2017-04-16 22:53
  • 1974

Sql Server 备份恢复脚本

<br />利用T-SQL语句,实现数据库的备份与还原的功能<br /><br />体现了SQL Server中的四个知识点:<br /><br />1. 获取SQL Server服务器上的默认目录<br /><br /&...
  • hanxin1987216
  • hanxin1987216
  • 2010-11-19 20:25
  • 3181

SQL 2008R2 误删除数据恢复方法(一)

原文出处:http://blog.csdn.net/dba_huangzj/article/details/8491327 本来想记录一下利用recovery for sql  server 这个软件恢复误删除的数据,但测试了几次不成功,就先转载这位大神的方法,太崇拜他,拿自己的测试库按照...
  • qyx0714
  • qyx0714
  • 2017-06-20 11:52
  • 1347

SQL Server2012 数据库恢复(mdf,ldf)

最简单的操作:方法一: master->右键,附加->添加你的mdf文件;数据恢复完成 方法二: 只有mdf文件和ldf文件,怎么恢复数据库数据文件的迁移(mdf,ldf)sql server数据库文件的迁移(mdf&ldf文件)
  • u010075060
  • u010075060
  • 2015-05-08 15:42
  • 1637

SqlServer2008R2部署到SqlServer2008备份还原库的坎坷之路

SqlServer2008R2部署到SqlServer2008 (1)备份还原bak文件(失败:版本不一致不兼容) (2)尝试导出导入脚本方式(用SqlServer management stutio生成的脚本太大700M在用户服务器上没有办法执行) (3)用户忘记SqlServer用户名密码及设置...
  • wxm0503
  • wxm0503
  • 2016-09-02 12:41
  • 1774
    个人资料
    • 访问:526782次
    • 积分:9037
    • 等级:
    • 排名:第2474名
    • 原创:362篇
    • 转载:14篇
    • 译文:1篇
    • 评论:137条
    博客专栏
    最新评论