数据库还原

部分还原(段落还原):分阶段还原和恢复包含多个文件组的数据库。

段落还原包括从主文件组开始(有时也从一个或多个辅助文件组开始)的一系列还原顺序。在还原顺序结束后,如果恢复的文件有效并且与数据库一致,则恢复的文件将直接变为联机状态。

所有的段落还原都从称为“部分还原顺序”的初始还原顺序开始。部分还原顺序至少还原和恢复主文件组,在简单恢复模式下还会还原和恢复所有读/写文件组。在段落还原顺序中,整个数据库都必须脱机。随后,数据库将处于联机状态,并且还原的文件组都处于可用状态。但是,尚未还原的任何文件组将保持脱机状态。

无论数据库采用何种恢复模式,部分还原顺序都从 RESTORE DATABASE 语句开始,该语句将还原完整备份并指定 PARTIAL 选项。PARTIAL 选项总是会启动一个新的段落还原;因此,在部分还原顺序的初始语句中,只能指定 PARTIAL 一次。当部分还原顺序完成并且数据库联机后,由于余下文件的恢复被推迟,这些文件的状态将变为“恢复已挂起”。

此后,段落还原通常包括一个或多个还原顺序,这些还原顺序称为“文件组还原顺序”。您可以等待执行特定的文件组还原顺序,等待的时间长短由您决定。每个文件组还原顺序将一个或多个脱机文件组还原并恢复到与数据库一致的点。文件组还原顺序的时间安排和数量取决于您的恢复目标、您想要还原的脱机文件组数量以及每个文件组还原顺序中还原的脱机文件组的数量。

联机段落还原可能引起事务延迟。如果仅还原了一部分文件组,则数据库中依赖联机文件组的事务可能会延迟。这是正常现象,因为整个数据库必须一致。如果段落还原将数据库恢复到某个点,在该点上有一个或多个活动事务会影响尚未还原并处于脱机状态的文件组,则将发生事务延迟。因为无法回滚事务,所以事务将延迟。
 

--1.1备份数据库 backup database test to disk = 'c:\test_1.bak' --1.2再次备份 backup database test to disk = 'c:\test_1.bak' --1.3使用设备上的第二个备份来还原数据库 restore database test from disk = 'c:\test_1.bak' with file = 2, replace --此选项让SQL Server覆盖当前已存在的数据库 --2.1查看备份中数据库的逻辑名称 restore filelistonly from disk = 'c:\test_1.bak' --2.2当需要把当前的备份在其他服务器上还原时可以指定新的物理路径 restore database test_other --新的数据库名称 from disk = 'c:\test_1.bak' with file = 2, move 'test' to 'c:\test_other.mdf', --数据的逻辑名称->新的物理路径 move 'test_log' to 'c:\test_other_log.log' --日志的逻辑名称->新的物理路径 --3.1这个备份创建3个文件,每个文件存储了三分之一的还原数据库时需要的备份信息 backup database test to disk = 'c:\test_stripping.bak', disk = 'd:\test_stripping.bak', disk = 'e:\test_stripping.bak' --3.2从条带备份来还原数据库 restore database test from disk = 'c:\test_stripping.bak', disk = 'd:\test_stripping.bak', disk = 'e:\test_stripping.bak' with replace --替换原来的数据库 --4.从事务日志还原 --4.1创建数据库 use master go if not exists(select name from sys.databases where name = 'Test') begin create database test end use test go --4.2添加数据 select * into dbo.SalesOrderDetail from AdventureWorks.Sales.SalesOrderHeader use master go --4.3完全备份 backup database test to disk = 'c:\test_full_1.bak' --4.4备份事务日志 backup log test to disk = 'c:\test_log_1.trn' --4.5再次备份事务日志 backup log test to disk = 'c:\test_log_2.trn' --4.6断开其他用户 use master go alter database test set single_user with rollback immediate --4.7还原完全备份 restore database test from disk = 'c:\test_full_1.bak' with replace, --由于原来的数据库还存在,所以必须替换 norecovery --必须指定此选项,让数据库处于restoring,这样才能继续还原日志 --4.8还原第一个事务日志 restore log test from disk = 'c:\test_log_1.trn' with norecovery --4.9还原第二个事务日志 restore log test from disk = 'c:\test_log_2.trn' with recovery --完成还原,使数据库处于online状态 --4.10删除表 use test go drop table dbo.SalesOrderDetail --4.11再次进行完全数据库备份 backup database test to disk = 'c:\test_full_2.bak' --4.12重建这个表 select * into dbo.SalesOrderDetail from AdventureWorks.Sales.SalesOrderHeader select GETDATE() --返回时间点 --4.13删除表 delete from dbo.SalesOrderDetail --4.14备份日志 backup log test to disk = 'c:\test_log_time.trn' use master go /*=============================================== 4.15还原完全备份 通过指定stopat会使得原来的数据库处于:正在还原状态, 其实用replace选项也是一样的,都会替换原来的数据库 =================================================*/ restore database test from disk = 'c:\test_full_2.bak' with norecovery, stopat = '2012-11-05 12:00:00.827' --此处也可以用选项replace,会替换原来的数据库 --4.16进行基于时间点的日志还原,还原到删除表之前的那个时间点,这样被删除的数据就能恢复 restore log test from disk = 'c:\test_log_time.trn' with recovery, --使用recovery选项的一瞬间,数据库置为联机状态 stopat = '2012-11-05 12:00:00.827' use test go --4.17查看之前被删除的数据,发现已经还原 select * from dbo.SalesOrderDetail --5.从差异备份还原数据库 use master go --5.1完全备份 backup database test to disk = 'c:\test_differential_full.bak' --5.2差异备份 backup database test to disk = 'c:\test_differential.bak' with differential --5.3日志备份 backup log test to disk = 'c:\test_differential_log.bak' --5.4从完全备份进行还原 restore database test from disk = 'c:\test_differential_full.bak' with norecovery, replace --5.5应用差异备份进行还原 restore database test from disk = 'c:\test_differential.bak' with norecovery --5.6应用日志还原 restore log test from disk = 'c:\test_differential_log.bak' with recovery --6.文件组还原 --6.1创建数据库 create database very_large_test on primary ( name = 'vlTest', filename= 'c:\vltest.mdf' ), filegroup fg1 ( name = 'vlTest1', filename= 'c:\vltest_fg1.ndf' ), ( name = 'vlTest2', filename= 'c:\vltest_fg2.ndf' ) log on ( name = 'vlTest_log', filename = 'c:\vlTest_log.log' ) --6.2备份文件组 backup database very_large_test filegroup = 'fg1' to disk = 'c:\very_large_test_fg.bak' with stats = 10 --6.3备份日志 backup log very_large_test to disk = 'c:\very_large_test_log.trn' /*============================================== 如果这样还原: 6.4.1还原文件组fg1: restore database very_large_test filegroup = 'fg1' from disk = 'c:\very_large_test_fg.bak' with norecovery, replace 6.4.2还原日志: restore log very_large_test from disk = 'c:\very_large_test_log.trn' with recovery 发现文件组fg1还是处于restoring状态: use very_large_test go select ds.name, --文件组名称 d.name, --物理文件路径 d.state_desc, --restoring状态 d.physical_name from sys.database_files d inner join sys.data_spaces ds on ds.data_space_id = d.data_space_id where ds.name = 'fg1' --文件组的名称 ==================================================*/ --6.4正确的还原方法 --6.4.1还原文件组fg1: restore database very_large_test filegroup = 'fg1' from disk = 'c:\very_large_test_fg.bak' with norecovery, replace --6.4.2还原日志: restore log very_large_test from disk = 'c:\very_large_test_log.trn' with norecovery /*=================================================================== 3.还原日志时虽然用了norecovery选项,但是文件组仍然处于restoring状态, 说明文件组fg2没有恢复到最新的,与数据库一致的状态,为了使得文件组fg1恢复到最新, 必须应用从上次备份日志以来数据库的变化, 当然也包含了文件组fg1的变化, 也就是应用尾日志 =====================================================================*/ --6.4.3备份尾日志 backup log very_large_test to disk = 'c:\very_large_test_trail_log.trn' --6.4.4还原日志,对于其他文件组么有变化,但是会让文件组fg1处于最新的一致状态 restore log very_large_test from disk= 'c:\very_large_test_trail_log.trn' with recovery --6.5另一种方法: --6.5.1还原日志: restore log very_large_test from disk = 'c:\very_large_test_log.trn' with recovery --6.5.2备份尾日志:只有文件组fg1处于restoring状态 --当主文件组是最新的,而文件组fg1不是最新的时候, --备份日志时使用选项norecovery并不会是整个数据库处于restoring状态 backup log very_large_test to disk = 'c:\very_large_test_trail_log.trn' with norecovery --备份完日志让数据库置为restoring状态 --6.5.3还原日志,对于其他文件组么有变化,但是会让文件组fg1处于最新的一致状态 restore log very_large_test from disk= 'c:\very_large_test_trail_log.trn' with recovery --6.5.4发现这个文件组处于online状态: use very_large_test go select ds.name, --文件组名称 d.name, --物理文件路径 d.state_desc, --restoring状态 d.physical_name from sys.database_files d inner join sys.data_spaces ds on ds.data_space_id = d.data_space_id where ds.name = 'fg1' --文件组的名称 --7.部分还原(段落还原) --7.1备份主文件组 backup database very_large_test filegroup = 'primary' to disk = 'c:\very_large_test_primary.bak' --7.2备份文件组fg1 backup database very_large_test filegroup = 'fg1' to disk = 'c:\very_large_test_fg1.bak' --7.3备份日志 backup log very_large_test to disk = 'c:\very_large_test_log_partial.trn' --7.4还原主文件组:这时整个数据库处于restoring状态 restore database very_large_test filegroup = 'primary' from disk = 'c:\very_large_test_primary.bak' with norecovery, partial, --指定PARTIAL 选项,该选项指示段落还原的开头 replace --替换原来的主文件组,其实就是替换整个数据库 --7.5恢复日志:使数据库处于online状态,但是文件组fg1处于RECOVERY_PENDING状态 restore log very_large_test from disk = 'c:\very_large_test_log_partial.trn' with recovery --7.6继续还原文件组fg1,文件组fg1处于restoring状态,表示文件组fg1还没有处于最新状态 restore database very_large_test filegroup = 'fg1' from disk = 'c:\very_large_test_fg1.bak' with recovery --7.7继续恢复日志,这个日志上面用于恢复主文件组,这样文件组fg1处于online状态 restore log very_large_test from disk = 'c:\very_large_test_log_partial.trn' with recovery --7.8再次完全备份 backup database very_large_test to disk = 'c:\vlt_full.bak' --7.8.1从完全备份中还原主文件组,从完全备份中来分别主文件组和辅助文件组 restore database very_large_test filegroup = 'primary' from disk = 'c:\vlt_full.bak' with norecovery, replace --7.8.2还原辅助额文件组 restore database very_large_test filegroup = 'fg1' from disk = 'c:\vlt_full.bak' with recovery, partial --7.8.3查看数据库,数据库中的文件的状态 select * from sys.databases where name = 'very_large_test' select * from sys.master_files where database_id = DB_ID('very_large_test') --8.在完整恢复模式或者大容量日志恢复模式下,进行页面还原,适用于可读写数据 --8.1 backup database very_large_test to disk = 'c:\vlt_full_page.bak' --8.2在suspect_pages系统表、错误日志、DBCC命令输出的返回中会标识出那些坏的页面 select database_id, file_id, page_id from msdb.dbo.suspect_pages --8.3进行页面还原 restore database very_large_test page = '1:8,1:15' from disk = 'c:\vlt_full_page.bak' with norecovery, replace --8.4备份尾日志 backup log very_large_test to disk = 'c:\vlt_full_log.trn' --8.5还原日志 restore log very_large_test from disk = 'c:\vlt_full_log.trn' --9.多种恢复路径 if exists(select 1 from sys.databases where name = 'test') begin drop database test end create database test --9.1完全备份 backup database test to disk = 'c:\test_full.bak' use test go create table t(v int) insert into t select OBJECT_ID from sys.objects --9.2第一次日志备份 backup log test to disk = 'c:\test_full_log_A.trn' select --最新的日志备份的日志序列号。这是前一个日志备份的结束LSN以及下一个日志备份的开始LSN last_log_backup_lsn, --26000000011500001 --标识数据库当前在其上处于活动状态的当前恢复分叉 recovery_fork_guid, --3BAA449E-BC84-43CC-A740-071556C1F477 --当前分叉点的日志序列号 fork_point_lsn, --NULL --恢复分叉开始的标识符 first_recovery_fork_guid --NULL from sys.database_recovery_status where database_id = DB_ID('test') insert into t select OBJECT_ID + 123456 from sys.objects --9.3第二次日志备份 backup log test to disk = 'c:\test_full_log_B.trn' --9.4还原完全备份 restore database test from disk = 'c:\test_full.bak' with norecovery, replace --9.5还原第一个日志备份 restore log test from disk = 'c:\test_full_log_A.trn' with recovery --9.9显示了当前的恢复分叉 select last_log_backup_lsn, --26000000011500001 recovery_fork_guid, --394AC596-1511-4946-9EF9-56532151BC2E fork_point_lsn, --26000000011500001 first_recovery_fork_guid --6E596B47-7659-4693-8C4D-91DD3CC2D9EB这是上一个恢复分叉的guid from sys.database_recovery_status where database_id = DB_ID('test')