MySQL数据库工程师入门实战课程视频教程
4265 人在学
完整备份不能截断事务日志,这是所有SQLServerDBA的一个常识,
为此,当数据库处于完整恢复模式时(非特别说明,下文所提到都是完整恢复模式下的数据库),DBA们必须频繁地使用事务日志备份的方式来防止日志文件变得过大。
这几乎成为了DBA们的一个定理,但,作为一个DBA,你证明过这个定理吗?你知道为什么完整备份不能截断事务日志吗?
首先我们先来看一个问题:
问题描述
通过SSMS中的维护计划配置了事务日志(TransactionLog)备份的Job,但测试执行后出现如下报错信息:
问题分析
仔细查看上述报错信息中的提示:
即中文如下:
这是由于此DB库从未执行过数据库完整备份或刚将数据库的日志级别从简单模式切换到完整模式。
见MSDN中(WorkingwithTransactionLogBackuPS)的描述
解决办法
执行一次完整的数据备份,然后再执行事务日志备份的Job
看完以上的例子,接下来看一下其它相关内容!
一个错误的”常识“
将一个完整备份还原到新数据库时,新数据库无论是mdf还是ldf,其大小都跟原始数据库一模一样,
以至于我们认为完整备份包括了mdf中所有数据和ldf中的所有事务日志。这几乎成为了一些DBA的”常识“。
正是如此,我们有”理由“认为:数据库在完整备份后,ldf中的事务日志应该被截断,没必要再保存一个副本。
让“常识”站不住脚
按照这个”常识“,既然完整备份中包含了原始数据库中所有的事务日志,那通过完整备份还原得到的新数据库应该也含有同样的事务日志。下面我们通过一个小实验来验证实际情况是否是这样。
验证思路:
结论1:
通过完整备份文件还原得到的数据库,尽管其LDF的大小与原数据库相同,但两者所包含的事务日志并不完全相同,如上例所述,原数据库test包含5条insert的事务日志,而新数据库test_new没有这些事务日志。如果完整备份截断了事务日志,则无论是原数据库的LDF文件还是完整备份文件,都将不包含事务日志,这无异于将数据库置于简单恢复模式下,显然不符合我们将数据库设置成完整恢复模式的初衷。
完整备份的那些事
通过上述实例我们已经有了足够的理由推翻那个错误的“常识”,但,这个例子似乎并不完美,因为它又将我们导向了另一个错误的极端——完整备份不包括任何事务日志。
真是这样的吗?
本质是是现象的根源,只有真正了解了数据库完整备份期间发生的那些事,我们才能揭开层层迷雾。
归纳起来,数据库的完整备份主要包括如下几个步骤:
①执行Checkpoint,并标记此时数据库中事务日志的LSN
②开始读取、拷贝datafiles中的数据
③结束datafiles的读取和拷贝,并记录此时最后一个活动日志的起始LSN
④读取并拷贝必需的日志文件
备注:读者在查看上述日志时,请先开启3004、3605、3502这三个跟踪标记。
DBCCTRACEON(3004,3605,3502,-1)
至此,我们已经明白了,在完整备份文件里,它虽然没有包含所有的事务日志,但在完整备份期间,拷贝日志的动作一直存在,按照SQLServer的说法,完整备份选择性的保存了数据库必需的事务日志。
为什么要选择性的保存这些必需事务日志呢?什么是“必需的事务日志”?而我的样例中新数据库为何没有任何事务日志?
在回答这些问题前,我们先看一下MSDN对完整备份文件的一个描述:
Fulldatabasebackupsrepresentthedatabaseatthetimethebackupfinished.
也就是说,完整备份文件能够呈现数据库在备份完成时间点的所有数据,那么,这些足够多的事务日志的目的肯定是为了将数据库还原到备份完成时的时间点。
有了这个概念,我们来看一个完整备份的场景,下图绿色的数字代表完整备份的每个步骤:
①执行事务A
②执行完整备份和checkpoint,开始读取和拷贝数据文件
③备份进程读取数据页X
④执行事务B,改变数据页X的数据
⑤结束事务B
⑥结束对数据文件的读取和拷贝
数据库的完整备份从时间点2持续到时间点7。
对于页面X,在时间点3做了备份后,在时间点5被事务B做了修改,因此,此时备份文件中页面X的数据已经过期了、不准确,而备份进程不会回过头来重新读取页面X。因为“完整备份文件必须呈现数据库在备份完成时间点的所有数据”,所以,数据库必须备份事务B的日志,以便在数据库通过重做此日志还原到时间点7的状态。
对于事务A,其执行的时间早于备份的开始时间,且在数据文件备份期间一直没有结束,是这次完整备份的活动事务。
尽管事务A没有提交,但时间点2的checkpoint已将事务A所做的修改写入到数据文件中,如果完整备份文件没有包含事务A的日志,则这些未提交的修改将无法得到回滚,导致数据不一致的情况发生。
综上所述:
结论2
如果在完整备份前不存在活动事务,则必需的事务日志范围:从备份开始时的LSN到备份结束时的LSN;
如果在完整备份前存在活动事务,则必需的事务日志范围:从最早活动事务开始的LSN到备份结束时的LSN;
在之前的样例中,因为5条insert语句在数据库备份前已经执行完成并提交了,所以备份文件不会保存这些日志,因而在还原得到的新数据库中看不到这些日志。
小编结语:
更多内容尽在课课家教育!