周勇强
摘要:如何设计良好的数据库备份方案,正确处理各种备份恢复问题,在出现各种软硬件故障及人为误操作问题后及时有效地恢复数据库,从而将数据丢失的风险降到最小,是很多数据库管理员面临的问题。该文力图从较深入的层次对SQL Server数据库的备份和恢复机制进行研究,将理论与实践相结合,分析一个有代表性的数据库备份恢复策略,提供有益的知识和经验。
关键词: SQL Server;备份;恢复;事务日志;检查点
中图分类号:TP311.13 文献标识码:A 文章编号:1009-3044(2018)18-0003-03
1 引言
SQL Server数据库已在各种应用系统中得到广泛应用,数据的重要性不言而喻,但各种软硬件故障及人为误操作问题难以避免,如果对SQL Server的数据库备份和恢复机制没有透彻的理解,就无法掌握正确的备份恢复技术。本文对SQL Server 2005及以上版本用户数据库的三种基本备份方式及相应的介质恢复技术进行研究,不涉及文件和文件组的备份恢复、系统数据库的备份恢复、高可用性方案等内容的探讨。
2 数据库备份
2.1 完整备份
完整备份是所有其他备份类型的基准备份,备份的内容为备份时的所有数据以及能将数据库基于这些数据恢复到备份结束时一致状态的事务日志。
使用不带DIFFERENTIAL选项的Backup Database命令执行完整备份:
Backup Database database_name TO backup_device
完整备份过程分为三个阶段:
① 执行检查点(Checkpoint)。将内存中的脏日志和脏数据存盘,对处于非完整日志序列维护状态的数据库进行日志截断,在日志文件中写入一段检查点记录(首条记录的LSN为检查点起点的LSN,即CheckpointLSN),内容为当前的MinLSN及所有活动事务的起始LSN,MinLSN是检查点起点的LSN和当前最早活动事务起点的LSN中的最老LSN。
② 数据转储。将所有已分配区(Extent)的数据复制到备份集。
③ 日志转储。将LSN满足条件FirstLSN≤LSN 2.2 差异备份 差异备份和完整备份类似,二者主要差别是备份的数据不同,差异备份以最近一次完整备份为基准,捕获基准备份后发生更改的数据区的数据。 使用带DIFFERENTIAL选项的BACKUP DATABASE命令执行差异备份: Backup Database database_name TO backup_device WITH DIFFERENTIAL 2.3 日志备份 使用BACKUP LOG命令执行日志备份: Backup LOG database_name TO backup_device 日志备份的范围是LSN满足条件FirstLSN≤LSN ① 如果是第一次执行事务日志备份,会备份所有日志记录,即FirstLSN是第一次完整备份的FirstLSN。 ② 否则备份上次日志备份以来新增的日志记录,即FirstLSN是上次日志备份的LastLSN。 LastLSN是执行日志备份时最后一个成功结束事务的下一个事务的开始LSN。 3 数据库恢复 如果将数据库的内容(数据和日志等)称为状态,则数据库备份就是把数据库当时的状态保存到备份集的过程,而数据库恢复则是通过重演备份集中内容来重建数据库并逐步推进(或称还原)数据库状态,最后重现数据库在恢复点正确状态的过程。 数据库恢复操作包括确定恢复点、备份尾日志、选择恢复链、执行数据库恢复命令四个基本步骤。 3.1 确定恢复点 恢复点是用户指定将数据库恢复到的点。恢复点可以是: ① 任何备份的尾部。 ② 日志备份包含的特定时点(在大容量日志恢复模式下,仅当日志备份不包含大容量更改,才能进行时点还原) 如果恢复点是故障点或最后一个备份与故障点之間的某个时点,则恢复所需的事务日志还在日志文件中。因为介质恢复是通过备份进行的,所以应先将处于日志文件尾部的这部分日志备份出来(称为尾日志备份)。需要注意的是,对于大容量日志恢复模式下的数据库,无法对包含大容量日志操作的活动日志执行尾日志备份。 实际上,对处于完整恢复模式或大容量日志恢复模式下的数据库,SQL Server如果检测到存在未备份的活动日志,总是要求在还原前执行尾日志备份。 3.2 备份尾日志 如果数据库服务可用,用带NORECOVERY选项的BACKUP LOG命令执行常规的尾日志备份。对受损数据库可尝试用NO_TRUNCATE或CONTINUE_AFTER_ERROR选项备份尾日志,这两个选项指示备份操作跳过错误继续进行,因此可能导致数据丢失。 如果以上方法都无法备份尾日志,或者服务无法启动,则只能尝试用非常规方法进行尾日志备份了,例如将日志文件“假载”到其他服务器上进行恢复。 有时需要在没有进行尾日志备份的情况下恢复数据库,例如尾日志已无法备份,或者恢复点不在尾日志中。可在数据库恢复的还原阶段使用以下方法跳过尾日志检测:(1)使用带REPLACE选项的RESTORE命令还原备份(跳过了一些安全性检查)。(2)还原时在每个RESTORE命令中使用STOPAT等时点还原参数指定已有日志备份包含的时点。(3)使用MOVE选项将数据库还原到新位置并具有新名称(如果还原到不同服务器可以使用相同名称)。
3.3 选择恢复链
恢复链是从已有备份序列中选出的、按备份先后次序排列的、用于恢复数据库的备份组合。恢复链起于完整备份、止于恢复点所在备份,中间可能还包含其他备份,用于将数据库状态沿着恢复链逐步还原到恢复点。
要成功恢复数据库,恢复链中每个备份都应该是可成功还原的,有四种备份可成功还原:
第1种 完整备份。
第2种 基准备份已被选进恢复链的差异备份。
第3种 恢复链中的第一个日志备份,如果和紧接在前面的完整备份(或差异备份)之间的LSN不存在缺口,即:日志備份的FirstLSN≤前一个备份的LastLSN≤日志备份的LastLSN,则日志备份是可成功还原的。
第4种 二个相邻的日志备份,如果二者之间的LSN首尾相连,即:后一个日志备份的FirstLSN=前一个日志备份的LastLSN,则后一个日志备份是可成功还原的。
3.4 执行数据库恢复命令
数据库恢复包括还原和恢复两个阶段。
(1) 还原(RESTORE)阶段
此阶段使用带“NORECOVERY”选项的RESTORE命令按备份的先后次序逐一还原恢复链中的各个备份,将数据库状态逐步推进,直到恢复点。
① 还原完整备份。
RESTORE DATABASE database_name FROM backup_device WITH NORECOVERY
此命令将完整备份中的数据复制到数据库并进行初始化,然后在此基础上应用备份中的日志记录(首先从备份集标头读出CheckpointLSN,据此在备份日志中找到对应的检查点记录,读出当时保存的MinLSN和所有活动事务的起点LSN,就可找到每个活动事务的所有日志记录,然后重做已完成事务,保留未完成事务),将数据库还原到完整备份完成时的状态。
② 还原差异备份
RESTORE DATABASE database_name FROM backup_device WITH NORECOVERY
此命令将备份集中的差异数据应用到数据库(用差异数据覆盖对应区),然后在此基础上应用备份中的日志记录(类似还原完整备份),将数据库推进到差异备份完成时的状态。
③ 还原日志备份
RESTORE LOG database_name FROM backup_device WITH NORECOVERY
此命令将备份集中的日志记录应用到数据库,重做已完成事务,保留未完成事务,将数据库推进到日志备份完成时的状态。
(2) 恢复(RECOVERY)阶段
所有备份还原后,数据库状态还原到了恢复点,接下来需要对还原后数据库中的存疑事务(可能不符合ACID特性的事务)进行处理,见图1。
存疑事务以事务日志中的最后一个检查点为界限分成二部分。第一部分是最后检查点之前的事务,这些事务都已被写入日志文件和数据文件,暂时无需处理。第二部分是最后检查点和恢复点之间的事务,这些事务可能存在两种问题:一是在日志中已提交的事务可能未被写入数据文件(T2、T4),原因是写日志和写数据是按WAL原则异步进行的,事务提交会将日志存盘,但数据可能尚未在恢复点之前存盘。二是未完成的事务被写到了数据库,原因是检查点会把未完成事务存盘,但直到恢复点还没有提交(T3、T5)。
此阶段使用带“RECOVERY”选项的RESTORE命令来处理存疑事务:
RESTORE DATABASE database_name WITH RECOVERY
此命令根据最后一个检查点的CheckpointLSN,在备份日志中找到对应的检查点记录,据此读出当时保存的MinLSN和所有活动事务的起点LSN,从而找到每个存疑事务的所有日志记录,然后重做未存盘的已完成事务(T2、T4),撤销已存盘的未完成事务(T3、T5),将数据库恢复到恢复点时的一致状态。
RECOVERY阶段的操作可以合并到RESTORE阶段的最后一个还原步骤。换言之,在还原阶段的最后一个步骤不使用NORECOVERY选项,而改用RECOVERY选项,该选项在还原最后一个备份后,立即进入恢复阶段。
4 实例研究
模拟典型的备份策略,分析备份信息,揭示备份间的内在联系,研究恢复到故障点的恢复链方案。
4.1 数据库备份
生成备份序列(用逗号分隔的备份名称表示):F1,L1,L2,D1,L3,L4,D2,L5,L6,F2,L7,L8,D3,L9,L10,D4,L11,其中备份名称由备份类型字母(F表示完整备份,D表示差异备份,L表示日志备份)加备份序号组成,每种备份类型独立编号。
RESTORE HEADERONLY命令用于查询备份集标头的基本备份信息,备份集的FirstLSN、LastLSN、CheckpointLSN、DatabaseBackupLSN反映了备份之间在日志和数据方面的内在联系。可用图示的方法直观显示这种关联,见图2。图中备份集的LSN范围用水平线段(FirstLSN≤LSN 4.2 数据库恢复 1)确定恢复点、备份尾日志 恢复点是故障点,因此首先执行尾日志备份。将尾日志备份Tail的LSN范围也标注在图2。 2)选择恢复链 按照选择恢复链的要求,借助图2,可方便地选出恢复链:
第一个备份必须是完整备份,用作后续还原的基准,可选F1或F2,但为了缩短恢复链,减少恢复时间,选F2。最后一个备份是包含恢复点的Tail。由于这两个备份并无直接关联,故需选择一些中间备份,以将数据库状态从F2逐步还原到Tail。
最佳方案:(F2,D4,L11,Tail)。F2属于第1种可成功还原备份,D4属于第2种,L11属于第3种,Tail属于第4种。这个方案的恢复链最短,故恢复时间最少。
备选方案:(F2,D3,L9,L10,L11, Tail)、(F2,,L7~L11, Tail)可用作最佳方案当差异备份D4或D3有问题时的替换方案;(F1,D2,L5~L11, Tail)及(F1,D1,L3~L11, Tail)、(F1,L1~L11, Tail)可用作最佳方案当完整备份F2有问题时的替换方案。
在以上方案中,任何一个备份都是必需的,如果其中一个备份丢失或被破坏,则恢复链中断,按此方案只能将数据库恢复到中断点之前的某个状态了,这里将这种恢复链称为最简恢复链。
实际上,在最简恢复链中还可加入其他备份,只要所加入的备份满足可成功还原的要求,并不影响恢复结果。例如最佳方案可修改为:(F1,F2,L7,D3,L9,D4,L11,TailLog),但这样做除了增加恢复时间别无意义。
5 结论
SQL Server的备份恢复,还包括文件和文件组的备份恢复、系统数据库的备份恢复等。DBA应在透彻理解备份恢复机制的基础上,通过深入细致的研究实践真正掌握备份恢复技术,如此才能从容应对各种复杂情况。
参考文献:
[1] 李爱武.SQL Server 2008 数据库技术内幕[M].北京:中国铁道出版社,2012.
[2] Delaney K.Inside Microsoft? SQL Server? 2005[M].The Storage Engine.US:Microsoft Press,2006.
[3] 赵松涛.SQL Server 2005 奥秘[M].北京:电子工业出版社,2007.
[4] 王珊,萨师煊.数据库系统概论(第5版)[M].北京:高等教育出版社,2014.
[5] 向猛,谢力靖.SQL Server 2005基于事务日志的备份与恢复深入研究[J].计算机系统应用,2013,22(6).
[6] Paul S. Randal.SQL Server:Understanding SQL Server Backups[EB/OL]. https://technet.microsoft.com/zh-cn/library/2009.07.sqlbackup.aspx#MtViewDropDownText.
[7] Paul S.Randal.SQL Server:Understanding Logging and Recovery in SQL Server[EB/OL]. https ://technet.microsoft.com /en-us/library/2009.02.logging.aspx.
[8] Paul S.Randal.SQL Server: Recovering from Disasters Using Backups[EB/OL]. https://technet.microsoft.com/en-us/library/ee677581.aspx.
[9] Paul S.Randal. Debunking a couple of myths around full database backups[EB/OL].https://www.sqlskills.com/blogs/paul/debunking-a-couple-of-myths-around-full-database-backups/.
[10] Paul S.Randal. More on how much transaction log a full backup includes [EB/OL]. https://www.sqlskills.com/blogs/paul/more-on-how-much-transaction-log-a-full-backup-includes/.
[11] 王渝次.信息系統灾难恢复的规划及实施[M].北京:北京交通大学出版社,2006.