原理
复制数据库里的所有信息,通过一个单个完整备份可将数据库恢复到某个时间点的状态。但由于数据库备份是一个在线的操作,一个大的完整数据库备份需要一段时间,数据库在该段时间内还会发生变化。所以完整数据库备份还要对部分事务日志进行备份,以使恢复数据库到一个事务一致的状态。
适用场景:小数据库
不适用场景:大数据库
差异备份原理
差异备份基于差异,备份要求数据库之前做过一次完整备份。差异备份仅捕获自该次完整备份后发生更改的数据,这个完整备份被称为差异备份的“基准”。差异备份仅仅包括建立差异基准后更改的数据。
差异备份相对完整备份的优点
每个日志备份都包括创建备份时处于活动状态的部分事务日志以及先前日志备份中未备份的所有日志记录。不间断的日志备份序列包含数据库的完整日志链。在完整恢复模式下,连续不断的日志链可以将数据库还原到任意时间点。
分级 | 完整备份 | 差异备份 | 日志备份 |
---|---|---|---|
数据库级 | 完整数据库备份 | 差异数据库备份 | (一般)日志备份 |
文件级 | 完整文件备份 | 差异文件备份 | (一般)日志备份 |
SQL Server 数据丢失的最大时间段
利用数据备份恢复机制保护数据,是不可能保证数据一点都不丢失的,SQL Server 不可能时时刻刻做数据库备份,每次备份之间总要有一定的时间间隔。此时间间隔之间的数据变化在下一次备份之前,是没有保护的。因此,数据丢失的最大时间段就是两次备份之间的时间间隔。
频繁备份是否合适?
既然数据丢失的最大时间段为两次备份之间的时间间隔,提高备份频率,降低备份间隔,从而减少数据丢失量。但是,备份越频繁,需要的投入也越多。
日志备份的局限性
使用日志备份,可将数据库恢复到故障点或特定的时间点。因此日志备份在备份策略中具有很重要的角色。但日志备份只能在完整恢复模式和有些大容量日志恢复模式的数据库上进行。制定备份策略,首先要决定是否需要日志备份,若需要,则数据库恢复模式就要选成完整模式,若不需要做日志备份,则数据库模式就要设置简单,否则会遇到日志文件无线增长问题。
简单恢复模式下,不能做日志备份,所以它只支持最简单的备份和还原方式,很容易管理。如果没有日志备份,则只能将数据库恢复到最后一次备份的结尾。若发生灾难,数据库最后一次备份之后所做的数据修改将全部丢失。
如下图所示,数据库有5个备份,灾难发生在 t6 时间点,因此只有在时间 t5 进行的最新的一份数据库备份需要被还原。还原此备份会将数据库恢复到 t5 这个时间点,t5 时间点之后的数据更新都会丢失。
优点
缺点
建议
限定充足的备份频率,以避免遗失大量数据。同时,频率也不能太高而让备份变得难以管理。
使用场景
只适合于可频繁备份的小型数据库
为降低风险,可引入差异备份,使用差异数据库备份补充数据库完整备份,从而降低工作损失风险的一种备份策略。
如下图所示,在第一次数据库完整备份后,连续建立了三次差异备份。第三次差异备份后,进行第二次数据库完整备份,建立新的差异基准。
差异备份相对完整备份的优点
适用场景
数据库数据量稍大,能够容忍较长时间数据丢失的。
简单恢复模式总结
不管是数据库完整备份和数据库差异备份,都不可能以比较频繁的频率进行,一般都只能在晚间进行。若数据库比较庞大,或者不允许比较长时间的数据丢失,这样的备份策略是不能满足要求的,必须引入日志备份,建立更为复杂,但是也更强大的恢复策略。
选取完整恢复模式可以使用日志备份。由于日志备份只复制上次日志备份以来的所有日志记录,所以开销会比数据库备份小很多,可以定义一种很频繁的频率(5分钟甚至更短)来做备份,以达到在最大限度内防止出现故障时丢失数据的目的。
使用日志备份的优点
使用日志备份的缺点
下图所示为完整恢复模式下的最简单备份策略,在此图中,已完成了数据库备份 Db_1 及两个例行日志备份 Log_1 和 Log_2。在 Log_2 日志备份后的某个时间,数据库出现故障。在还原这三个备份前,DBA 必须首先备份活动日志(日志尾部),然后还原 Db_1 、Log_1 、Log_2,并且不恢复数据库,接着 DBA 还原并恢复尾(Tail)日志文件。这一步可以把数据库恢复到故障点,从而恢复所有数据。如果尾日志能够成功地备份和恢复,这次灾难可能甚至不会带来任何数据丢失。如果灾难毁坏的时日志文件,使得尾日志不能成功备份和恢复,这次灾难造成的数据丢失就是从 Log_2 以后的所有修改。
数据丢失最大时间段
在第一个完整数据库备份完成,并且常规日志备份开始之后,潜在的工作丢失风险存在事件仅为数据库损坏时间点,即到上一次常规日志备份的那一段时间。
建议
建议经常执行日志备份,以将工作丢失的风险限定在业务要求所允许的范围内。
缺点
每1小时做一次日志备份。每周在周日做一次数据库完整备份。若灾难在周5发生,则不得不恢复 5*24=120个日志备份。恢复日志文件过多其花费的时间成本较大。
模拟场景
为了最大程度地缩短还原时间,可对相同数据进行一系列差异备份做补充。
下图所示为使用差异数据库备份及一系列例行日志备份来补充完整数据库备份。使用事务日志备份可缩短潜在的工作丢失风险的存在时间,使该风险仅在最新日志备份之后存在。在第一个数据库备份完成后,每天做一个差异数据库备份,而在工作时间进行若干日志备份。
上图中第一个数据库备份创建之前,数据库存在潜在的工作丢失风险(从时间 t0 到时间 t1)。该备份建立之后,例行日志备份将工作丢失的风险降为丢失自最近日志备份之后所做的修改(最近备份的时间为 t14)。如果发生故障,则应立即尝试备份活动日志(尾部日志),若此“尾部日志备份”成功,则数据库可还原到故障点。
下面以 AdventureWorksDW2018 数据库为例,来了解完整恢复模式下的数据库备份
AdventureWorksDW 数据库的安装请参考 SQL SERVER 自带数据库下载安装
实践前准备
清空表 msdb..backupset 上 2018/09/28
之前的记录,注意时间
USE msdb;
GO
EXEC sp_delete_backuphistory @oldest_date = '09/28/2018';
将 AdventureWorksDW2018
库的恢复模式修改为完整恢复模式,否则会报 4208
错误
USE master ;
ALTER DATABASE AdventureWorksDW2018 SET RECOVERY FULL ;
显示 AdventureWorksDW2018 这个数据库历史上曾经的备份信息。
use msdb;
select distinct s.first_lsn, s.last_lsn,
s.database_backup_lsn, s.backup_start_date, s.backup_finish_date,
s.type, y.physical_device_name
from msdb..backupset s inner join
msdb..backupfile f on f.backup_set_id = s.backup_set_id inner join
msdb..backupmediaset m on s.media_set_id = m.media_set_id inner join
msdb..backupmediafamily y on m.media_set_id = y.media_set_id
where (s.database_name = 'AdventureWorksDW2018')
order by s.backup_finish_date desc;
备份信息字段含义
对于日志备份来讲
字段 | 含义 |
---|---|
first_lsn | 标识备份集中第一个日志记录的日志序列号 |
last_lsn | 标识备份集之后的下一条日志记录的日志序列号 |
(fisrt_lsn, last_lsn-1) | 标识此日志备份所包含的所有日志序列 |
last_lsn-1 | 表示前面一条日志序列号,而不表示日志序列号减 1,因为日志序列号虽然是递增的,但并不表示一定以 1 为单位递增 |
(fisrt_lsn, last_lsn) | 表示做数据恢复时,在做 roll forward(前滚)动作时,一定要遍历的 LSN,不然的话数据库在做恢复的时候,数据会不一致 |
database_backup_lsn | 标识上一次数据库做全备份的起始 LSN |
TYPE
标识数据库备份的类型
类型 | 含义 |
---|---|
D | 数据库 |
L | 日志 |
I | 差异数据库 |
F | 文件或文件组 |
1. 对数据库做一个全备份
BACKUP DATABASE [AdventureWorksDW2018] TO DISK='F:\backup\AdvFull1.bak'
2. 对数据库做一个操作,然后做一个日志备份
--drop table t1;
use AdventureWorksDW2018;
create table t1(number int, name nvarchar(50));
insert into t1 values(1, 'a');
go
BACKUP LOG [AdventureWorksDW2018] TO DISK='F:\backup\AdvLog2.bak'
再次执行查询,可看到又添加了一条新的记录如下图所示。此备份时日志备份,LSN 是从 57000000028800001
到57000000039200001
3. 对数据库做一个操作,再做一个日志备份
use AdventureWorksDW2018;
insert into t1 values(2, 'b');
go
BACKUP LOG [AdventureWorksDW2018] TO DISK='F:\backup\AdvLog3.bak'
再次执行查询,可看到又添加了一条新的记录如下图所示。这个备份日志备份,LSN 是从 57000000039200001
到 57000000040800001
,可观察到这个日志备份的 first_lsn
和上一次日志备份的 last_lsn
一定是一样的。这是因为数据库在做日志备份的时候,LSN 要求是连续的。
4.对数据库做一个操作,再做一个差异备份
use AdventureWorksDW2018;
insert into t1 values(3, 'c');
go
BACKUP DATABASE [AdventureWorksDW2018] TO DISK='F:\backup\AdvDiff4.bak' WITH DIFFERENTIAL;
再次执行查询,可看到又添加了一条新的记录,这个备份时差异备份,如下图所示
5. 一直这样操作,最后对数据库做一次日志操作,如下图所示
-- 插入一条数据,再做一个差异备份
use AdventureWorksDW2018;
insert into t1 values(4, 'd');
go
BACKUP DATABASE [AdventureWorksDW2018] TO DISK='F:\backup\AdvDiff5.bak' WITH DIFFERENTIAL;
-- 插入一条数据,再做一个日志备份
use AdventureWorksDW2018;
insert into t1 values(6, 'f');
go
BACKUP LOG [AdventureWorksDW2018] TO DISK='F:\backup\AdvLog7.bak'
-- 插入一条数据,再做一个日志备份
use AdventureWorksDW2018;
insert into t1 values(8, '8');
go
BACKUP LOG [AdventureWorksDW2018] TO DISK='F:\backup\AdvLog8.bak'
-- 插入一条数据,再做一个差异备份
use AdventureWorksDW2018;
insert into t1 values(9, '9');
go
BACKUP DATABASE [AdventureWorksDW2018] TO DISK='F:\backup\AdvDiff9.bak' WITH DIFFERENTIAL;
-- 插入一条数据,再做一个日志备份
use AdventureWorksDW2018;
insert into t1 values(10, '10');
go
BACKUP LOG [AdventureWorksDW2018] TO DISK='F:\backup\AdvLog10.bak'
-- 插入一条数据,再做一个日志备份
use AdventureWorksDW2018;
insert into t1 values(11, '11');
go
BACKUP LOG [AdventureWorksDW2018] TO DISK='F:\backup\AdvLog11.bak'
总结
first
不管是全备份还是差异备份,都不会影响 LSN 的序列。因此,即使最近的几个全备份或差异备份受损,只要有一个全备份,以及该全备份后所有的日志备份,我们也是能够完整无缺地把数据恢复出来,只是恢复的时间会稍微长一点。中间的差异备份或其他全备份只是减少了需要恢复的日志备份数目。这进一步说明了日志备份的重要性。
second
日志备份的 LSN 是连续的。否则在恢复的时候,会碰到日志链断裂的问题,恢复时不能继续下去的。
<
查看或更改数据库的恢复模式 (SQL Server)
维护计划实现备份:每周数据库完整备份、每天差异备份、每小时日志备份
SQL Server 2012入门备份与恢复数据库篇:总揽
windows7 设置文件夹的权限设置