在SQL Server里如何进行页级别的恢复

在今天的文章里我想谈下每个DBA应该知道的一个重要话题:在SQL Server里如何进行页级别还原操作。假设在SQL Server里你有一个损坏的页,你要从最近的数据库备份只还原有问题的页,而不是还原整个数据库。

我们来破坏一个页

第一步我想向你展示下如何建立表(或索引)里有个特定页损坏的情景,这里我们会进行一些魔术,因为开箱即用(out-of-box)的SQL
Server本身不会引入任何损坏的页(如果有的话,恭喜你找到了一个BUG)。我们从创建一个新的数据库,往新建的表插入一些记录开始。

 1 USE master
 2 GO
 3
 4 CREATE DATABASE PageLevelRestores
 5 GO
 6
 7 USE PageLevelRestores
 8 GO
 9
10 -- Create a table where every record fits onto 1 page of 8kb
11 CREATE TABLE Test
12 (
13     Filler CHAR(8000)
14 )
15 GO
16
17 -- Insert 4 records
18 INSERT INTO Test VALUES (REPLICATE('A', 8000))
19 INSERT INTO Test VALUES (REPLICATE('B', 8000))
20 INSERT INTO Test VALUES (REPLICATE('C', 8000))
21 INSERT INTO Test VALUES (REPLICATE('D', 8000))
22 GO
23
24 -- Retrieve the selected records
25 SELECT * FROM Test
26 GO

下一步我进行完整数据库备份。这就是说这个备份包含了属于Test表的所有页。这非常重要,因为接下来我们会破坏这个表的一个特定页。为了找出属于Test表的页,我用DBCC IND命令来返回所有属于这个表的页。

1 -- Perform a full database backup
2 BACKUP DATABASE PageLevelRestores TO DISK = N'C:\Backups\PageLevelRestores.bak'
3 GO
4
5 -- Retrieve the first data page for the specified table (columns PageFID and PagePID)
6 DBCC IND(PageLevelRestores, Test, -1)
7 GO

为了破坏一个特定的页,我使用未公开的DBCC WRITEPAGE命令。是的,在SQL Server里有个可用的DBCC WRITEPAGE命令,但请不要告诉任何人……

 1 ALTER DATABASE PageLevelRestores SET SINGLE_USER WITH ROLLBACK IMMEDIATE
 2 GO
 3
 4 -- Let's corrupt page 90...
 5 DBCC WRITEPAGE(PageLevelRestores, 1, 90, 0, 1, 0x41, 1)
 6 DBCC WRITEPAGE(PageLevelRestores, 1, 90, 1, 1, 0x41, 1)
 7 DBCC WRITEPAGE(PageLevelRestores, 1, 90, 2, 1, 0x41, 1)
 8 GO
 9
10 ALTER DATABASE PageLevelRestores SET MULTI_USER
11 GO

为了使用DBCC WRITEPAGE,问题数据库必须设置如代码所示的单用户模式(Single-User
mode)。这里我模拟了有个存储错误,写了一些垃圾到存储的页里(是的,这个在你工作中也会碰到!)。现在当你从表再次读取数据库,SQL
Server会返回你一个824 I/O错误,因为对损坏页的校验失败了。

1 -- Retrieve the selected records
2 SELECT * FROM Test
3 GO

一旦SQL Server在I/O访问期间检测到一个损坏的页,在msdb.dbo.suspect_pages里,损坏的页也会被记录,如下图所示。

1 SELECT * FROM msdb.dbo.suspect_pages

对msdb里对特定表进行监控是个很好的想法,可以得到你的数据库里是否有损坏的页。现在我们让事情变得更糟糕,下列代码会往表里插入另外一条记录。

1 -- Now we have additional transaction that we don't want to loose...
2 INSERT INTO Test VALUES (REPLICATE('E', 8000))
3 GO

我们来还原损坏的页

现在你是DBA,你想恢复这个数据库到正确状态且不丢失数据(像我们在最后一步插入的记录)。你会怎么做?首先你要进行所谓的尾日志备份(Tail-Log Backup):你要备份自上次事务日志备份后的已发生的事务。

1 -- Backup the transaction log
2 BACKUP LOG PageLevelRestores TO
3     DISK = 'C:\Backups\PageLevelRestores_LOG1.bak'
4     WITH INIT
5 GO

在这里还没有进行过事务日志备份,因此我们的备份会包含自完整备份后,所有已执行的事务。现在我们可以在SQL
Server里初始页级别还原操作。这里你使用传统的RESTORE
DATABASE的T-SQL命令,但你只要指定想要还原的页,不用还原整个数据库,我们只要还原有问题的页。如果你在处理很大的数据库,这会有很大的区别。

1 USE master
2 -- Restore full database backup
3 RESTORE DATABASE PageLevelRestores
4     PAGE = '1:90'
5     FROM DISK = 'C:\Backups\PageLevelRestores.bak'
6     WITH NORECOVERY
7 GO

现在到了棘手的部分:在RESTORE DATABASE的T-SQL命令后,你要进行另一个事务日志备份。这个另外的日志备份是需要的,因为接下来你要保证在这个可用页进行的所有改变用作还原。没有这个额外的日志备份,SQL Server不能把你的页重新上线。

1 -- Backup the tail of the log...
2 BACKUP LOG PageLevelRestores TO
3     DISK = 'C:\Backups\PageLevelRestores_LOG_TAIL.bak'
4     WITH INIT
5 GO

进行完这个额外日志备份后,最后你可以在正确的顺序里恢复所有的日志备份,最后你可以把数据库恢复上线。

 1 -- Restore all available log backups in the correct order
 2 RESTORE LOG PageLevelRestores FROM
 3     DISK = 'C:\Backups\PageLevelRestores_LOG1.bak'
 4     WITH NORECOVERY
 5 GO
 6
 7 -- Finally restore the tail log backup
 8 RESTORE LOG PageLevelRestores FROM
 9     DISK = 'C:\Backups\PageLevelRestores_LOG_TAIL.bak'
10     WITH NORECOVERY
11 GO
12
13 -- Finally finish with the restore sequence
14 RESTORE DATABASE PageLevelRestores WITH RECOVERY
15 GO

现在当你再次查询表时,你会看到SELECT语句成功执行没有任何I/O错误,在这个表里没有丢失任何数据。还是很简单,是不是?

1 USE PageLevelRestores
2 GO
3
4 -- Retrieve the selected records
5 SELECT * FROM Test
6 GO

小结

在SQL Server里如何进行页级别恢复操作是每个DBA应该知道的。它是你工具箱里最重要的工具之一——尤其当你在处理很大的数据库时。不用恢复整个数据库,你只恢复有问题的页,整个恢复过程会非常快。

最后给你一个问题,各位看官:你是否有过在SQL Server进行页级别的恢复,如果是的话——对你来说它有多难/简单?请畅所欲言!

感谢关注!

作者:WoodyTu

来源:51CTO

时间: 2024-08-23 02:52:10

在SQL Server里如何进行页级别的恢复的相关文章

简单介绍SQL Server里的闩锁_MsSql

在今天的文章里我想谈下SQL Server使用的更高级的,轻量级的同步对象:闩锁(Latch).闩锁是SQL Server存储引擎使用轻量级同步对象,用来保护多线程访问内存内结构.文章的第1部分我会介绍SQL Server里为什么需要闩锁,在第2部分我会给你介绍各个闩锁类型,还有你如何能对它们进行故障排除. 为什么我们需要闩锁?闩锁首次在SQL Server 7.0里引入,同时微软首次引入了行级别锁(row-level locking).对于行级别锁引入闩锁的概念是非常重要的,不然的话在内存中会

简单介绍SQL Server里的闩锁

在今天的文章里我想谈下SQL Server使用的更高级的,轻量级的同步对象:闩锁(Latch).闩锁是SQL Server存储引擎使用轻量级同步对象,用来保护多线程访问内存内结构.文章的第1部分我会介绍SQL Server里为什么需要闩锁,在第2部分我会给你介绍各个闩锁类型,还有你如何能对它们进行故障排除. 为什么我们需要闩锁? 闩锁首次在SQL Server 7.0里引入,同时微软首次引入了行级别锁(row-level locking).对于行级别锁引入闩锁的概念是非常重要的,不然的话在内存中

浅析SQL Server在可序列化隔离级别下,防止幻读的范围锁的锁定问题

原文:浅析SQL Server在可序列化隔离级别下,防止幻读的范围锁的锁定问题   本文出处:http://www.cnblogs.com/wy123/p/7501261.html (保留出处并非什么原创作品权利,本人拙作还远远达不到,仅仅是为了链接到原文,因为后续对可能存在的一些错误进行修正或补充,无他)     数据库在处理并发事物的过程中,在不同的隔离级别下有不同的锁表现,在非可序列化隔离级别下,存在着脏读,不可重复读,丢失更新,幻读等情况.本文不讨论脏读和不可重复读以及丢失更新的情形,仅

SQL Server :理解DCM页

原文:SQL Server :理解DCM页 我们已经讨论了各种不同的页,包括数据页.GAM与SGAM页.PFS页,还有IAM页.今天我们来看下差异变更页(Differential Change Map:DCM ),还有差异备份(differential backups). 差异变更页(Differential Change Map:DCM ) :SQL Server使用差异变更页来跟踪自上次完全备份后修改过的区.DCM页在数据文件里是第6页.DCM页用来跟踪完全备份后修改过的区.DCM为每个跟踪

SQL Server :理解IAM 页

原文:SQL Server :理解IAM 页 在以前的文章里,我们讨论了数据页,GAM和SGAM,还有PFS页.今天我们一起来讨论下索引分配映射(Index Allocation Map:IAM)页. 在SQL Server 2005和以后的版本里,分配单元(allocation units)以下三个类型: IN_ROW_DATA  用于存储堆分区或索引分区,即heap和B-tree. LOB_DATA 用于存储大型对象 (LOB) 数据类型,例如 xml.varbinary(max) 和 va

SQL Server :理解BCM页

原文:SQL Server :理解BCM页 今天我们来讨论下批量更改映射(Bulk Changed Map:BCM)页,还有大容量日志恢复模式( bulk logged recovery model )如何运作的. 批量更改映射(Bulk Changed Map:BCM):SQL Server使用BCM页来跟踪自上次完全备份后,被大容量日志操作修改的区.在数据库文件里,BCM页是第7页.BCM对每个跟踪的页都有一个位.如果这个位标记是1,表示对应区在上次日志备份后因为大容量日志操作而修改.如果这

分析MS SQL Server里函数的两种用法

server|函数 SQL Server里函数的两种用法(可以代替游标) 1. 因为update里不能用存储过程,然而要根据更新表的某些字段还要进行计算.我们常常采用游标的方法,这里用函数的方法实现. 函数部分: 以下是引用片段: CREATE FUNCTION [DBO].[FUN_GETTIME] (@TASKPHASEID INT) RETURNS FLOAT AS BEGIN DECLARE @TASKID INT, @HOUR FLOAT, @PERCENT FLOAT, @RETUR

SQL Server里函数的两种用法(可以代替游标)

server|函数|游标 SQL Server里函数的两种用法(可以代替游标)1. 因为update里不能用存储过程,然而要根据更新表的某些字段还要进行计算.我们常常采用游标的方法,这里用函数的方法实现. 函数部分:CREATE FUNCTION [DBO].[FUN_GETTIME] (@TASKPHASEID INT) RETURNS FLOAT AS BEGIN   DECLARE @TASKID INT,          @HOUR FLOAT,           @PERCENT

SQL Server里如何查询表结构

环境:SQL Server 2008 R2 问题:查询表结构命令 对MySQL和Oracle数据库熟悉的朋友知道用desc就可以查询一张表的结构,但是在SQL Server里执行desc命令会报错. desc Student; --关键字 'desc' 附近有语法错误. 现提供两条命令查询表结构: 1.sp_help table_name; 如: sp_help Student; 执行效果如下: 2.sp_columnstable_name; 如: sp_columns Student; 执行效