5.1. 实验的目的、内容与要求
5.1.1. 实验目的
(1) 综合运用学习的数据库安全管理、备份与恢复、数据库管理工具的使用的相关知识完成数据库和备份与恢复。
(2) 通过实验进一步掌握数据库简单恢复模式与完整恢复模式下的数据库备份与恢复方法中的基本概念与操作方法。
(3) 理解数据库备份的重要性以及不同备份与恢复方法的差异。
SQL Server数据库的备份可以使用Tansact-SQL(简称T-SQL,是SQL Server的一种可编程SQL语言)也可以使用SSMS来完成,这两种方法无论是在简单恢复模式还是在完整恢复模式下的备份都是可以用的。这里,我们主要以T-SQL的方法演示备份与恢复的操作,要求在实验中掌握这种备份与恢复方法,而对于使用SSMS进行备份与恢复则只需要了解即可。
5.1.2. 实验内容
(1) 实验一 简单恢复模式下数据库的备份与恢复
参考实验指导书中的例子,设计一个简单恢复模式下的数据库备份与恢复的实验方案,方案中要完成一个完整备份和多个差异备份,进行数据库的多次恢复实验,每次将数据库恢复到不同的数据库备份。在备份过程中设计相应的操作以验证多次不同恢复的差异。
(2) 实验二 完整恢复模式下数据库的备份与恢复
参考实验指导书中的示例,设计一个完整恢复模式下数据库备份与恢复的方案,方案要完成完整恢复(恢复到故障点)和时间点恢复(部分恢复)并比较两者的差异。方案中还需要设计相应的操作以便验证完整恢复和时间点恢复的差异。
5.1.3. 实验报告
注意在实验的过程中观察每次实验的结果,包括结果是否正确,备份的内容、处理的数据量、备份的时间,如果是恢复则还需要注意在恢复后的状态变化。这些相应的内容均需要写到实验报告中。
5.2. 备份与恢复概述
所有的恢复模式都允许备份完整或部分的 SQL Server 数据库或数据库的单个文件或文件组。不能创建表级备份。
5.2.1. 备份类型
数据的备份(“数据备份”)的范围可以是完整的数据库、部分数据库或者一组文件或文件组。对于这些范围,SQL Server 均支持完整和差异备份:
(1) 完整备份
“完整备份”包括特定数据库(或者一组特定的文件组或文件)中的所有数据,以及可以恢复这些数据的足够的日志。
(2) 差异备份
“差异备份”基于数据的最新完整备份,完整备份称为差异的“基准”或者差异基准。差异备份仅包括自建立差异基准后发生更改的数据。通常,建立基准备份之后很短时间内执行的差异备份比完整备份更小,创建速度也更快。因此,使用差异备份可以加快进行频繁备份的速度,从而降低数据丢失的风险。通常,一个差异基准会由若干个相继的差异备份使用。还原时,首先还原完整备份,然后再还原最新的差异备份。
经过一段时间后,随着数据库的更新,包含在差异备份中的数据量会增加。这使得创建和还原备份的速度变慢。因此,必须重新创建一个完整备份,为另一个系列的差异备份提供新的差异基准。
(3) 日志备份
第一次数据备份之后,在完整恢复模式或大容量日志恢复模式下,需要定期进行“事务日志备份”(或“日志备份”)。每个日志备份都包括创建备份时处于活动状态的部分事务日志,以及先前日志备份中未备份的所有日志记录。
5.2.2. 恢复模式
SQL Server有简单恢复模式与完整恢复模式,两种不同的恢复模式下备份与恢复的方法都不相同,在进行备份前首先要确定是使用哪一种恢复模式。简单恢复模式备份与恢复都比较简单,但有可能会丢失最近对数据库所做的修改,而完整恢复模式相对复杂,丢失数据的风险更小,且可以恢复到某一时间点。
(1) 简单恢复模式
简单恢复模式提供简单的备份与还原形式。由于不会备份事务日志,所以备份易于管理。不过,也正是由于这个原因,只能将数据还原到数据最近一次备份的结尾。如果发生故障,则数据库最近一次备份之后所做的修改将全部丢失。
下图显示简单恢复模式下最简单的备份和还原策略。其中有5个数据库备份,但只有在时间t5进行的备份才需要还原(根据需要也可以还原t5以前的备份,但只能还原一个备份)。还原这个备份会将数据库恢复到它t5这个时间点,所有后面的修改(以t6方块表示)都会丢失。
图 5 1 简单恢复模式下的备份策略
在简单恢复模式下,工作损失风险会随时间经过而增加,直到进行下一个完整备份或差异备份为止。可以通过提高备份的频率以减少丢失数据的风险,但过高的备份频率会影响应用的性能,同时也会使备份变得难以管理。
下图显示只使用数据库完整备份的备份计划的工作损失风险,这个策略只适合可频繁备份的小型数据库。
图 5 2 仅使用完整备份的备份策略
图 5 3中使用数据库完整备份与差异备份,在时间t1完成一个数据库完整备份,之后在t2、t3和t4分别完成3个差异备份。在t1的差异备份比较小,但在t4的差异备份已经与完整备份相差无几,因此在t5时又开始一个新的完整备份。在这个备份策略下,如果在t1到t5之间发生故障,比如t4,则先恢复t1的完整备份,然后恢复t3的完整备份。
图 5 3 使用完整备份与差异备份的备份策略
(2) 完整恢复模式
完整恢复模式使用日志备份在最大范围内防止出现故障时丢失数据,这种模式需要备份和还原事务日志(“日志备份”)。使用日志备份的优点是允许将数据库还原到日志备份内包含的任何时点(“时间点恢复”)。假定可以在发生严重故障后备份活动日志,则可将数据库一直还原到没有发生数据丢失的故障点处。使用日志备份的缺点是它们会增加还原时间和复杂性。但在大多数的应用环境中还是使用日志备份。
下图显示了在完整恢复模式下的最简单的备份策略。在此图中,已完成了数据库备份 Db_1 以及两个例行日志备份 Log_1 和 Log_2。在 Log_2 日志备份后的某个时间,数据库出现数据丢失。在还原这三个备份前,数据库管理员必须备份活动日志(日志尾部)。然后还原 Db_1、Log_1 和 Log_2,而不恢复数据库。接着数据库管理员还原并恢复尾日志备份 (Tail)。这将把数据库恢复到故障点,从而恢复所有数据。
图 5 4 完整恢复模式下数据库和日志备份
在第一个完整数据库备份完成并且常规日志备份开始之后,潜在的工作丢失风险的存在时间仅为数据库损坏时以及执行最新的常规日志备份时。因此,建议经常执行日志备份,以将工作丢失的风险限定在业务要求所允许的范围内。
出现故障后,可以尝试备份“日志尾部”(尚未备份的日志)。如果尾日志备份成功,则可以通过将数据库还原到故障点来避免任何工作丢失。
可以使用一系列日志备份将数据库前滚到其中一个日志备份中的任意时间点。若要最大程度地降低风险,建议安排例行日志备份。请注意,为了最大程度地缩短还原时间,可以对相同数据进行一系列差异备份以补充每个完整备份。
5 5显示的备份策略使用差异数据库备份及一系列例行日志备份来补充完整数据库备份。使用事务日志备份可缩短潜在的工作丢失风险的存在时间,使该风险仅在最新日志备份之后存在。在第一个数据库备份完成后,会接着进行三个差异数据库备份。第三个差异备份很大,因此下一次数据库备份时(t13)开始一个新的数据库完整备份。该数据库备份将成为新的差异基准。
5 5 使用完整备份、差异备份和日志备份
在此图中的第一个数据库备份创建之前,数据库存在潜在的工作丢失风险(从时间 t0 到时间 t1)。该备份建立之后,例行日志备份将工作丢失的风险降为丢失自最近日志备份之后所做的更改(在此图中,最近备份的时间为 t14)。如果发生故障,则数据库管理员应该立即尝试备份活动日志(日志尾部)。如果此“尾日志备份”成功,则数据库可以还原到故障点。
5.2.3. 日志备份
在完整恢复模式和大容量日志恢复模式下,执行例行事务日志备份(“日志备份”)对于恢复数据十分必要。使用日志备份,可以将数据库恢复到故障点或特定的时间点。建议经常进行日志备份,其频率应足够支持业务需求,尤其是对损坏的日志驱动器可能导致的数据丢失的容忍程度降低时。适当的日志备份频率取决于对工作丢失风险的容忍程度与所能存储、管理和潜在还原的日志备份数量之间的平衡。每 15 到 30 分钟进行一次日志备份可能就已足够。但是如果业务要求将工作丢失的风险最小化,请考虑进行更频繁的日志备份。频繁的日志备份还有增加日志截断频率的优点,其结果是日志文件更小。
在创建第一个日志备份之前,必须先创建完整备份(如数据库备份)。此后,必须定期备份事务日志。这不仅能最小化工作丢失风险,还有助于事务日志的截断。通常,事务日志在每次常规日志备份之后截断。但是,日志截断也可能会延迟。
(1) 日志链
连续的日志备份序列称为“日志链”。日志链从数据库的完整备份开始。通常,仅当第一次备份数据库时,或者将恢复模式从简单恢复模式切换到完整恢复模式之后,才会开始一个新的日志链。
若要将数据库还原到故障点,必须保证日志链是完整的。也就是说,事务日志备份的连续序列必须能够延续到故障点。对于数据库备份,日志备份序列必须从数据库备份的结尾处开始延续。
(2) 使用日志备份恢复数据库
还原日志备份将前滚事务日志中记录的更改,使数据库恢复到开始执行日志备份操作时的状态。还原数据库时,必须还原在所还原完整数据库备份之后创建的日志备份。通常情况下,在还原最新数据或差异备份后,必须还原一系列日志备份直到到达恢复点。然后恢复数据库。这将回滚所有在恢复开始时未完成的事务并使数据库在线。恢复数据库后,不得再还原任何备份。
5.3. 简单恢复模式下的备份与恢复
图 5 6中给出了一个简单恢复模式下备份与恢复数据库AdventureWorks的示例。在示例中,第1步使用ALTER DATABASE命令将该数据库设置为简单恢复模式。虽然数据库的默认恢复模式为简单恢复模式,但建议在所有的情况下仍然使用该命令以确保数据库在备份之前是工作在简单恢复模式下,特别是在使用定制备份在情况下更是如此。
第2步使用BACKUP DATABASE进行数据库的完整备份。备份中的引号每个数据库的备份都必须有至少一个完整备份,在恢复时首先要恢复完整备份。
内容是备份文件集的文件名,文件名中的路径必须是已经存在的路径。一每次备份会产生一个备份集,而一个备份集文件可以保存多个备份集。
备份集在备份集文件中有一个唯一的编号,如果不加指定,文件中的第一个备份集的编号是1,第2个备份集的编号是2,以此类推。备份集的编号在管理备份时和恢复数据库时使用。第1步中的备份集在该文件中的编号为1。
WITH FORMAT表示格式化备份集文件。如果该文件已经存在,则会清空其中的内容,如果文件不存,则创建一个新的文件。
第3步是执行一个差异数据库备份,同样使用命令BACKUP DATABASE。但不同的是在命令中使用WITH DIFFERENTIAL指定进行的备份是一个差异备份,如果是完整备份则不需要指定。注意该步骤中使用了与第2步相同的备份集文件,这样该备份集的编号为2。如果是使用一个新的文件则备份集的编号仍然是1。
建议在进行第三步之前对数据库进行一些修改操作,如创建一个表或插入一些记录到已有的表中等。这些操作的目的是用于验证在数据库恢复后是否将相应的修改操作结果也恢复回来了。
差异备份根据需要可以进行多次,在实际应用中往往是进行若干个差异备份,这里为了简单只进行一次差异备份。如果在实验的过程中进行多个差异备份,建议在每次差异备份之前都进行对数据库的修改操作,以便在恢复时验证修改结果的恢复情况。
图 5 6 简单恢复模式的数据库备份与恢复示例
在操作第4步之前,应当将数据库删除。在完成第4步之后注意观察数据库的状态(应当是处于还原状态)。数据库是不会自动显示,需要刷新操作。
第4步是还原数据库的完整备份,使用命令RESTORE DATABASE。FROM DISK 指定备份集文件,该文件是第1和2步中备份集的文件。WITH FILE=1,NORECOVERY表示从该备份集文件中的第1个备份集(它是一个完整备份)进行恢复(每次恢复的第一个备份必须是完整备份),NORECOVERY表示只进行数据库的还原而不进行恢复。还原的操作只是将数据从备份集中拷贝到数据库的文件中,它不会进行末提交事务的撤消,也不会重做记录的日志文件中已经提交的事务。这时的数据库仍然处于还原状态,要把数据库变成正常状态还需要使用其它的命令(后面的示例有相应的内容)。在还原状态下的数据库可以继续还原后续的差异备份。如果没有NORECOVERY选项,则数据库在完成还原后会进行数据库的恢复操作,如果在还原与恢复的过程中执行正常,则数据库恢复到正常状态。也可以根据需要决定是在哪一个备份(完整或差异都可以)恢复数据库。
第5步是还原数据库的差异备份。FILE=2表示从备份集文件中的第2个备份集进行还原。RECOVERY表示还原后执行数据库的恢复,该选项不是必须的,因为默认的方式是RECOVERY。
在完成第5步后,注意观察数据库已经变成正常的状态了。此时可以查询数据库的内容以验证差异备份前数据库的修改操作结果是否恢复。
5.4. 完整恢复模式下的备份与恢复
5.4.1. 恢复到故障点的备份与恢复示例
在该示例中,备份由一个数据库的完整备份和两个日志备份组成(USE master;
–1. 将数据库修改为完整恢复模式.
ALTER DATABASE AdventureWorks SET RECOVERY FULL;
GO
–2. 执行数据库的完整备份.
BACKUP DATABASE AdventureWorks
TO DISK = ‘C:\SQLServerBackups\AdventureWorks.bak’
WITH FORMAT;
GO
–3. 创建日志文件备份.
BACKUP LOG AdventureWorks
TO DISK = ‘C:\SQLServerBackups\AdventureWorks.bak’;
GO
–4.创建尾日志备份.
BACKUP LOG AdventureWorks
TO DISK = ‘C:\SQLServerBackups\AdventureWorks.bak’
WITH NORECOVERY;
GO
图 5 7)。其中,数据库的备份可以由一个完整备份也可以由一个完整备份和若干个差异备份组成,我们把这些备份统称为数据库的备份以区别于日志备份。也就是说,完整恢复模式下的备份由数据库备份和日志备份组成。
USE master;
–1. 将数据库修改为完整恢复模式.
ALTER DATABASE AdventureWorks SET RECOVERY FULL;
GO
–2. 执行数据库的完整备份.
BACKUP DATABASE AdventureWorks
TO DISK = ‘C:\SQLServerBackups\AdventureWorks.bak’
WITH FORMAT;
GO
–3. 创建日志文件备份.
BACKUP LOG AdventureWorks
TO DISK = ‘C:\SQLServerBackups\AdventureWorks.bak’;
GO
–4.创建尾日志备份.
BACKUP LOG AdventureWorks
TO DISK = ‘C:\SQLServerBackups\AdventureWorks.bak’
WITH NORECOVERY;
GO
图 5 7 完整恢复模式下的数据库备份示例一
在USE master;
–1. 将数据库修改为完整恢复模式.
ALTER DATABASE AdventureWorks SET RECOVERY FULL;
GO
–2. 执行数据库的完整备份.
BACKUP DATABASE AdventureWorks
TO DISK = ‘C:\SQLServerBackups\AdventureWorks.bak’
WITH FORMAT;
GO
–3. 创建日志文件备份.
BACKUP LOG AdventureWorks
TO DISK = ‘C:\SQLServerBackups\AdventureWorks.bak’;
GO
–4.创建尾日志备份.
BACKUP LOG AdventureWorks
TO DISK = ‘C:\SQLServerBackups\AdventureWorks.bak’
WITH NORECOVERY;
GO
图 5 7中的日志备份中,只有一个常规日志备份和一个尾日志备份,在实际应用环境中,常规日志备份可能有多个(也可能没有)。
步骤1将数据库设置为完整恢复模式,缺省情况下,数据库的恢复模式为简单恢复模式。
步骤2执行数据库的完整备份,FORMAT选项表示如果备份集文件存在则清空其内容,否则创建一个新的备份集文件。
步骤3使用BACKUP LOG创建一个常规日志备份,并且将备份写到与数据库完整备份相同的备份集文件中。这样,该日志备份的备份集编号为2。
步骤4使用BACKUP LOG创建一个尾日志备份。尾日志备份使用“NORECOVERY”选项进行备份,尾日志备份完成后不能再对该数据库进行任何备份,这时候备份的数据库处于还原状态。尾日志备份通常在发生故障后进行备份,但任何一个使用NORECOVERY选项进行的日志备份都是尾日志备份。
如果最后一个日志备份不是尾日志备份,而在完成最后一个备份后又对数据库进行了修改,则在进行步骤5时会出现下面的错误:
消息3159,级别16,状态1,第2 行
尚未备份数据库”AdventureWorks” 的日志尾部。如果该日志包含您不希望丢失的工作,请使用BACKUP LOG WITH NORECOVERY 备份该日志。请使用RESTORE 语句的 WITH REPLACE 或WITH STOPAT 子句来只覆盖该日志的内容。
消息3013,级别16,状态1,第2 行
RESTORE DATABASE 正在异常终止。
当故障发生后,我们可以使用图 5 8给出的操作步骤恢复备份的数据库。该恢复将数据库恢复到故障点。其中,
步骤5还原数据库的完整备份,FILE=1指定从备份集的编号为1 的备份集恢复,该备份集是USE master;
–1. 将数据库修改为完整恢复模式.
ALTER DATABASE AdventureWorks SET RECOVERY FULL;
GO
–2. 执行数据库的完整备份.
BACKUP DATABASE AdventureWorks
TO DISK = ‘C:\SQLServerBackups\AdventureWorks.bak’
WITH FORMAT;
GO
–3. 创建日志文件备份.
BACKUP LOG AdventureWorks
TO DISK = ‘C:\SQLServerBackups\AdventureWorks.bak’;
GO
–4.创建尾日志备份.
BACKUP LOG AdventureWorks
TO DISK = ‘C:\SQLServerBackups\AdventureWorks.bak’
WITH NORECOVERY;
GO
图 5 7中第2步创建的数据库完整备份。NORECOVERY指定只还原数据库而不进行恢复。
步骤6还原第1个常规日志备份(实际上只有一个)。
步骤7还原第2个日志备份(实际上是尾日志备份)。
步骤8恢复数据库。在完成该步骤后数据库恢复到正常状态,而前面的操作完成后,数据库处于还原状态。
在操作该示例时,建议在每次备从份前对数据库进行一些相应的操作,在恢复完成后验证这些修改操作的结果是否恢复。
图 5 8 完整恢复模式下数据库的恢复示例一
5.4.2. 恢复到时间点的备份与恢复示例
在上一节中,数据库的恢复是恢复到故障点,如果缺少一个日志的备份,比如发生故障导致日志文件被破坏,或者应用要求恢复过去某一个时间,如恢复到错误删除一个表之前的状态,这时必须使用时间点恢复。这一节我们通过一个例子演示这种时间点恢复。
时间点恢复是部分恢复的一种,其它的方法还可以基于日志序列号、事务序列号等。
该示例由图 5 9、图 5 10和图 5 11组成,所有的操作步骤都在其中。
图 5 9 完整恢复模式下和数据库备份示例二
步骤1将数据库AdventureWorks设置为完整恢复模式。
步骤2首先删除数据库中的表,如果该表不存在,则该命令会出现借误,不过它并不会影响后续的操作。之后,创建该表。在删除和创建表时使用了表的命名空间,AdventureWorks.dbo.Table_1表示数据库AdventureWorks中的架构dbo中的表Table_1。
步骤3创建一个数据库的完整备份,该备份所使用的备份集文件是C:\SQLServerBackups\AdventureWorks.bak。在创建该备份之前,备份集文件中的路径必须已经存在。因为使用了FORMAT选项,所以所产生的备份集一定是该备份集文件中的第1个备份集。
在图 5 10中的日志备份中,我们在每次备份前插入一条记录到前面所创建的表中,插入记录的值是当前系统的时间,它使用T-SQL函数current_timestamp,命令select current_timestamp是查询当前的时间。
在执行完步骤5之后,不要立即执行步骤6和步骤7,让第一个日志备份与第二个日志备份之间有些间隔以便于后面设定恢复的时间点,如果两者的时间间隔太短,则时间点设置就比较困难。
图 5 10 完整恢复模式下的日志备份示例二
图 5 11中的操作是恢复所备份的数据库,这里设置的时间点如果是插入第一条记录之前的时间,则在执行完步骤9之后数据库就会恢复成正常状态,所插入的两条记录均不会恢复;如果时间点设置在两条记录的时间之间,则在执行完步骤10数据库就会恢复到正常状态,则只有第1条记录会恢复;如果设置到插入第2条记录之后,则还需要执行第步骤11数据库才会恢复成正常状态,2条记录均会恢复。
图 5 11 数据库的时间点恢复示例
这个示例演示了数据库的时间点恢复,具体操作时间可以通过变化时间点以测试不同的恢复结果。