欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

sql server 备份与恢复系列七 页面还原

程序员文章站 2022-05-25 16:22:02
一.概述 当数据库发生损坏,数据库的每个文件都能打开,只是其中的一些页面坏了,这种情况可以借助DBCC CHECKDB进行数据库检查修复。如果要保证数据库不丢失,或修复不好,管理员只能做数据库完整恢复,为了少数页面恢复整个数据库,代价是比较高的,sql server引入了页面还原功能,可以指定还原若 ......

一.概述

  当数据库发生损坏,数据库的每个文件都能打开,只是其中的一些页面坏了,这种情况可以借助dbcc checkdb进行数据库检查修复。如果要保证数据库不丢失,或修复不好,管理员只能做数据库完整恢复,为了少数页面恢复整个数据库,代价是比较高的,sql server引入了页面还原功能,可以指定还原若干页面,从而能够大大节省数据库恢复时间。
  页面还原用于修复隔离的损坏页面,还原恢复时间比文件更快,减少了还原过程中处于离线的数据量,当某个文件的大量页面都出现损坏,可以直接还原该文件(需要有文件备份)。要进行还原的页面是在访问该页面,遇到错误而标记为"可疑",可以试试去找msdb.dbo.suspect_pages表。在页面还原后,也需要恢复所有的日志文件备份
  1.1 还原的限制,不能还原的页
    (1)事务日志不能还原。
    (2)分配页面:全局分配映射gam页面,共享全局分配映射sgam页面和可用空间pfs页面,这些系统页面损坏,页面还原无法恢复。
    (3)所有数据文件的页面0 的(文件启动页面)。
    (4)页面1:9的(数据库启动页面)。
  1.2 还原条件
    (1) 必需使用完整恢复模式。
    (2) 只读文件组中的页面无法还原。
    (3) 还原顺序必须是从完整备份,文件备份中恢复页面开始。
    (4) 页面还原需要截止到当前日志文件的连续日志备份
    (5) 数据库备份和页面还原不能同时进行。

二.还原步骤      

  (1) 获取要还原的损坏页面的页id,当sql server遇到校验或残缺写错误时,会返回页面编号。可以通过查询msdb数据库里的suspect_pages表,或者监视事件和errorlog文件里记录的错误信息,查找到损坏的页面id。
  (2) 从包含页的完整数据库备份,文件备份或文件组备份开始进行页面还原。在restore database 语句中,使用page子句列出所有要还原的页id。
  (3) 应用最近的差异备份。
  (4) 应用后续的日志备份。
  (5) 创建新的数据库尾日志备份。
  (6) 还原新的尾日志备份,应用这个新的日志备份后,就完成了页面还原。

三. 备份

  为了演示损坏的数据页面,新建一个pagetest表,初始化三个page页,后面人为的破坏一个数据页面。

use backuppagetest
-- 创建表
create table pagetest
(
    id int,
    name varchar(8000)
)
-- 产生
insert into pagetest
select 1, replicate('a',8000)
insert into pagetest
select 1, replicate('b',8000)
insert into pagetest
select 1, replicate('c',8000)

 sys.system_internals_allocation_units 查看分配页情况

 sql server 备份与恢复系列七 页面还原

/* 
第1个参数:库名
第2个参数:表名
第3个参数:-1: 显示所有iam、数据分页、及指定对象上全部索引的索引分页
pagefid: 文件id
pagetype=1 指数据页面
pagetype=10 iam页面
*/ 
-- 未公开的命令,语法如下:
dbcc ind(dbname,tablename,-1)

  sql server 备份与恢复系列七 页面还原

use master
-- 完整备份
backup database  backuppagetest to backuptestdevice

四 模拟页面损坏

  使用pagepid为89的数据页面进行演示,通过dbcc page查看该页面,知道该页数据是存储的第三条数据。

dbcc traceon (3604)
dbcc page('backuppagetest',1,89,1)

  sql server 备份与恢复系列七 页面还原

  使用 dbcc wirtepage来模拟该面损坏:

-- 未公开的命令语法为如下
dbcc writepage ({ dbid, 'dbname' }, fileid, pageid, offset, length, data)
-- 模拟页面损坏
dbcc writepage(backuppagetest,1,89,96,10,0x65656565656565656565)

sql server 备份与恢复系列七 页面还原

-- 查询该表时,第三条数据显示null
select * from pagetest

  sql server 备份与恢复系列七 页面还原

--更新第三条数据,结果报错
update pagetest set  id=2  where id is null

  sql server 备份与恢复系列七 页面还原

-- 插入第4条是成功的
insert into pagetest
select 4, replicate('d',8000)

  sql server 备份与恢复系列七 页面还原

五. 获取要修复的数据页面 

-- 使用checkdb检查
dbcc checkdb(backuppagetest)

  通过校验,提示无法处理面(1:89)如下图

  sql server 备份与恢复系列七 页面还原

六. 还原

use master
--从完整数据库备份,开始还原,指定要还原的page页
restore database backuppagetest page='1:89' from backuptestdevice with file=39,  norecovery
--创建新的尾日志备份
backup log backuppagetest to backuptestdevice

   此时访问数据表pagetest将会发错,如下图所示,表明在还原过程中数据是不可访问的。

 sql server 备份与恢复系列七 页面还原

sql server 备份与恢复系列七 页面还原

--最后还原新的尾日志备份
restore log backuppagetest from backuptestdevice with file=40,  recovery

   数据修复过来了,如下图:

  sql server 备份与恢复系列七 页面还原

  再次checkdb 检查表状态

  sql server 备份与恢复系列七 页面还原