此为本小组翻译外国作家文章,原文链接为http://www.sqlservercentral.com/articles/Stairway+Series/73785/
楼梯到事务日志管理SQL Server,5级:在完整恢复模式的日志管理
由汤尼戴维斯,2012 / 01 / 27
该系列
这篇文章是楼梯系列的一部分:在SQL Server事务日志管理的楼梯
当事情进展顺利,没有需要特别在意日志或它是如何工作的交易。你只需要相信,每一个数据库已经有正确的备份制度。当事情出错时,了解事务日志是重要的采取纠正措施,特别是在一个时间点恢复数据库是必需的,迫切的!Tony Davis只给出正确的细节层次,每个DBA都应该知道。
在这个层面我们会检讨为何以及如何执行日志备份,当工作在全部
恢复模式,以及如何执行数据库恢复使用这些日志备份文件,在完整数据库备份相结合。全部
恢复模式支持数据库恢复到任何时间点内可用的日志备份,如果尾日志备份可以用,到最后提交的事务的时间,在发生故障。
会得到什么样的记录?
进入全部
恢复模式下,所有的操作都是完全记录。为插入
,更新
和删除
操作,这意味着每行被修改,会有一个日志记录描述交易进行声明的ID,当交易开始和结束,哪些页面被改变,数据变化了,等等。
操作可以最小日志记录选择
成
,散装
插入
和创造
指数
,仍然完全记录在工作全部
恢复模式,但它是略有不同。行受这些操作不记录个别;只数据库页被记录,因为他们得到了。这降低了测井听到这样的操作,同时确保存在的信息存在,需要进行回滚,重做和时间点恢复。Kalen Delaney已经发表了一些调查记录选择进入
(http://sqlblog.com/blogs/kalen_delaney/archive/2011/03/15/what-gets-logged-for-select-into.aspx)和重建索引(http://sqlblog.com/blogs/kalen_delaney/archive/2011/03/08/what-gets-logged-for-index-rebuilds.aspx)操作,在全部
和bulk_logged
恢复模式。在最小日志记录操作日志记录的差异,当工作在bulk_logged
模式,更详细的讨论,在6级–管理登录 大容量日志 恢复模式。
为什么备份事务日志?
进入全部
恢复模式,只有一个日志备份可以导致日志截断。因此,事务日志将保持完整的交易自上次事务日志备份进行记录。因为所有的操作都是完全记录,日志文件会变得很大,很快,在繁忙的系统。
因此,当工作在全部
恢复模式,它是 至关重要的你做的常规事务日志备份,除了完整备份和差异备份,可选。很多新手或兼职DBA执行完全备份对数据库,但他们不执行事务日志备份。因此,事务日志不会被截断,它成长直到它的驱动器上的磁盘空间耗尽,导致SQL服务器停止工作。
该日志截断将尽快日志备份是发生,假设从以前的备份,没有其他因素推迟截断发生了一个检查站,如数据备份或还原操作。对于一个完整的,可能会延迟恢复体截断因子列表,以及因素,保持大量的日志活动,否则就不需要,如一个流氓,长期未提交的事务或数据库镜像或复制的过程中,看到:http://msdn.microsoft.com/en-gb/library/ms345414.aspx。
copy_only
备份事务日志
copy_only
备份事务日志不截断事务日志。一copy_only
日志备份存在“独立”的正常日志备份方案;它不破的日志备份链。
总之,事务日志备份执行允许还原和恢复到之前的某个时间点的双重目的,以及控制事务日志的大小。可能交易的最常见的原因是工作日志的相关问题全部
恢复模式和不带日志备份,日志备份或没有足够频繁的大小来控制事务日志文件。
如果你不确定是否事务日志备份正在采取在一个给定的数据库,那么你可以简单地询问备份集表中msdb
数据库,使用查询类似于清单5.1所示。
使用msdb;
选择backup_set_id,
backup_start_date,
backup_finish_date,
backup_size,
recovery_model,
[型]
在类型
柱,一个D
代表一个数据库备份,l
一个日志备份I
差异备份。
注意,因为在这种数据备份集表可以被操纵而不影响备份和恢复性能,你可能想验证你的结果从这个查询,通过查询sys.database_recovery_status
看的价值last_log_backup_lsn
(参见清单3.5),或sys.databases
表看的价值log_reuse_wait_desc
(将返回log_backup
如果备份是必需的)。
如何备份事务日志
正如前面所讨论的,这是不可能执行事务日志备份不先以至少一个完整的备份。事实上,如果你有一个数据库,在全部
恢复模式,但从来没有备份,那么它将不会工作全部
恢复模式。该数据库将自动截断模式直到进行第一次完整备份。
所有的数据库备份,日志全,或以其他方式,进行备份
命令。命令接受无数次的选择,这是记录在这里:http://msdn.microsoft.com/en-us/library/ms186865.aspx。然而,在其最基本的,这往往是如何使用,命令执行完全备份到磁盘如下:
数据库备份<em>数据库</em>磁盘=“<em>filelocation \ databasename.bak</em>”;
如果这是首次进行的备份,databasename.bak
文件会在指定的目录中创建。如果此文件已经存在,则默认行为是,追加后续的备份文件。重写此行为,并规定任何现有文件将被覆盖,我们可以使用初始化
选项,如下:
数据库备份<em>数据库</em>磁盘=“<em>filelocation \ databasename.bak</em>与初始化;
最常见的,然而,每个后续的备份是一个独特的名字;更在这即将到来的部分,<em>恢复到故障点</em>。
在每次定期(如每日)全备份,会有频繁的日志备份(例如每小时),其基本的命令非常相似:
备份日志<em>数据库</em>磁盘=“<em>filelocation \ databasename_log.bak</em>”;
存储日志备份
显然,备份的数据和日志文件不能存放在同一个驱动器,主机的活档案。如果硬盘有硬件故障然后你所有的副本都将随着生活的文件丢失,和备份就白费了。文件要备份到一个独立的设备,或备份到本地,镜像驱动器。
日志备份的频率
在以前的水平,注意,你可以将日志备份每15分钟,甚至更多。在这种情况下,为了避免需要恢复大量的事务日志文件,你可以选择备份方案包括全备份和差异备份的穿插,穿插的事务日志备份。
在现实中,备份方案更多的是理想与现实之间的妥协,对损失数据的真实风险评估之间,它将使公司的成本和费用,减少风险。许多重要的商业应用程序使用较为简单,但严格的备份方案,也许涉及定期夜间全备份加上每小时的事务日志备份。
日志备份的频率也可由交易数量的数据库对象。非常繁忙的数据库,它可能需要备份经常为了控制日志大小。
有没有简单的方法来计算经常把日志备份。大多数数据库管理员会在多久日志备份应采取他们的最佳估计,然后观察文件的生长特性,然后调整备份方案以防止过大的。
日志链如何打破它
值得注意的是,这是不可能执行事务日志备份不先以至少一个完整的备份。为了恢复数据库到一个时间点,或者一个特定的日志备份或到某个时间点结束在一个特定的日志备份,必须存在一个完整的不间断的链条,日志记录,从后全采取的第一个日志备份(备份或差异备份),直到失败这一点。这是被称为<strong>日志链</strong>。
有许多方法来打破链,如果你这样做就意味着你只能将数据库恢复到日志备份事件发生前采取断链的时间。总之,断链是<strong>不是</strong>一个好主意,如果你关心的能力来恢复您的数据。两打破链的最常见的方式包括:
- <strong>丢失或损坏的事务日志备份文件</strong>–只能恢复到上次好的日志备份。日志链又将开始在下一个好的完整备份或差异备份。
- 开关
简约
恢复模式如果你从–全部
到简约
恢复模式,这将打破链作为一个检查点会煽动和事务日志可以立即截断。当你回到全部
模式,你将需要一个完整备份恢复日志链。事实上,直到你完全备份,数据库将自动截断模式和无法备份日志文件。
SQL Server 2008前,有一对夫妇的命令,即备份
日志
与no_log
或备份
日志
与
truncate_only
(他们在功能上是等价的),发的时候,会迫使一个日志文件截断,所以打破链。你不应该在任何版本的SQL Server发出这些命令,但我在这里提到它们,他们仍然会被粗心的使用,当试图处理一个“失控的日志文件”,而不理解它所具有的意义为他们恢复他们的数据库能力。看到8级–的帮助下,我的日志已满,更多的细节。
尾日志备份
只要你有一个最近的完整备份和一个完整的日志链,你可以恢复你的数据库的一种状态,它存在于最终的日志备份结束之前的任何失败。然而,假如你把事务日志备份时,的时间,以及故障发生在下午1:45。你可能会失去45分钟的数据;事实上,如果失败是灾难性的,所以生活事务日志是无法挽回的,那么就是数据量会失去你。
然而,有时候生活事务日志仍然可以即使数据文件不可用,特别是如果事务日志包含在一个单独的、专用的驱动。如果是这种情况,你应该备份事务日志的生活即执行的日志记录最后备份自上次日志备份后生成的。这将在日志文件中捕获住剩余的日志记录,到故障点。这被称为<strong>尾日志备份</strong>,是最后的行动开始前应进行还原和恢复操作。
尾日志备份和最小日志记录操作
如果数据文件不可用,由于数据库故障,和日志的尾部含有最小日志记录操作,那么就不可能做尾日志备份,这就需要在数据文件中获取数据的变化程度。这将包括更详细的<em>6级,</em><em>管理</em><em>事务日志在大容量日志模式</em>。
如果你想恢复数据库在线,然后备份日志尾部是如下:
备份日志<em>数据库</em>磁盘=“<em>filelocation \ databasename_log.bak</em>“WITH NORECOVERY
这个使用NORECOVERY
选项使数据库在恢复状态,假设下一个行动,你要执行的是一个恢复
。如果数据库处于离线状态,启动不了,你还是应该尝试备份日志尾部如刚才所描述的(虽然使用NORECOVERY
选项可以省略,因为没有交易将进步)。
如果你确信日志文件损坏,文件显示,作为最后的手段,你想做一尾日志备份:
备份日志<em>数据库</em>磁盘=“<em>filelocation \ databasename_log.bak</em> ‘ continue_after_error
如果主数据库和数据文件被损坏,但日志是可用的,微软建议重建master数据库,然后备份活动日志。然而,这些主题在这楼梯的范围,我是指你的文件的详情。看到http://msdn.microsoft.com/en-us/library/ms190952.aspx。
进行还原和恢复
进行尾日志备份,如果可能的话,下一步就是要恢复上次完全备份(其次是差异备份,如果合适的话),然后恢复日志备份文件的完整序列,包括尾日志备份。这个序列的基本语法恢复操作如下:
恢复数据库日志} { |<em>数据库</em>从磁盘=“<em>filelocation \ filename.bak</em>“WITH NORECOVERY;
如果当你恢复你的省略与
使用NORECOVERY
选项,则默认恢复
命令将与
恢复
。换句话说,SQL Server将数据和日志文件的调和,向前滚动完成交易然后回滚未完成事务的必要。通过指定与
使用NORECOVERY
,我们指示SQL Server,我们正在进入一个还原顺序,更多的操作必须向前滚动,在任何可以进行回滚。在还原顺序还原最后一个备份后,数据库就可以恢复如下:
还原数据库的语句
一个共同的要求是要将数据库还原到不同的位置,在这种情况下,你可以简单地将文件作为恢复过程的一部分,这里所描述的那样:http://msdn.microsoft.com/en-us/library/ms190255.aspx。
恢复后的Database Failure
下面的示例说明如何回应一个故障恢复数据库,该数据库的数据文件无法访问。
完全恢复到故障点
假设“活”的事务日志可以是一个数据库失败后得出的,也许是由硬件故障引起的,那么在理论上应该可以恢复和恢复数据库到故障点,采用以下步骤:
- 备份日志尾部
- 恢复最近的完整备份(加微分,如果适用的话)
- 恢复,反过来,每个事务日志备份后,全部采取(或差)失败的时间前完成备份
- 还原尾日志备份
- 恢复数据库
很多例子发现在线图书展示恢复从“备份集”,就是一个“装置”,所有的备份存储。在实践中,这意味着,当备份到磁盘备份设备是单.bak
位于某处的磁盘文件。
所以,例如,清单5.2中的例子使用一个备份集组成的一个完整备份和事务日志备份,并说明如何执行完全恢复。为了运行这段代码,你需要先创建其中
数据库然后插入一些样本数据行(为方便起见,脚本来做这个,createandpopulatetestdb.sql,包含在这一等级的代码下载)。你还需要创建在本地“备份”目录C:
你的数据库服务器的驱动器,或修改文件路径适当。
-- Perform a full backup of the Test database
-- The WITH FORMAT option starts a new backup set
-- Be careful, as it will overwrite any existing sets
-- The full backup becomes the first file in the set
BACKUP DATABASE TestDB
TO DISK = ‘C:\Backups\TestDB.bak‘
WITH FORMAT;
GO
-- Perform a transaction log backup of the Test database
-- This is the second file in the set
BACKUP Log TestDB
TO DISK = ‘C:\Backups\TestDB.bak‘
GO
-- ....<FAILURE OCCURS HERE>....
-- The RESTORE HEADERONLY command is optional.
-- It simply confirms the files that comprise
-- the current set
RESTORE HEADERONLY
FROM DISK = ‘C:\Backups\TestDB.bak‘
GO
-- Back up the tail of the log to prepare for restore
-- This will become the third file of the bakup set
BACKUP Log TestDB
TO DISK = ‘C:\Backups\TestDB.bak‘
WITH NORECOVERY;
GO
然而,使用备份集似乎未的时候,数据库备份到磁带。当备份到磁盘,这是一个坏主意,用这个方案,因为,当然,备份文件会迅速成长非常大。
在实践中,每个完整备份和事务日志备份文件将被单独命名的情况更为常见,而且可能加盖,备份时的日期和时间。例如,大多数第三方备份工具,受欢迎的社区生成的脚本,加上维护计划向导/ SSMS的设计师,都会创建单独的文件如<em>adventureworks_full_20080904_000001.bak</em>邮戳日期。
因此,一个更常见的备份和恢复方案将使用唯一命名的备份,如清单5.3所示。
USE master;
BACKUP DATABASE TestDB
TO DISK =‘C:\Backups\TestDB.bak‘
WITH INIT;
GO
-- Perform a transaction log backup of the Test database
BACKUP Log TestDB
TO DISK =‘C:\Backups\TestDB_log.bak‘
WITH INIT;
GO
-- ....<FAILURE OCCURS HERE>....
-- Back up the tail of the log to prepare for restore
BACKUP Log TestDB
TO DISK =‘C:\Backups\TestDB_taillog.bak‘
WITH NORECOVERY, INIT;
GO
-- Restore the full backup
RESTORE DATABASE TestDB
FROM DISK = ‘C:\Backups\TestDB.bak‘
WITH NORECOVERY;
-- Apply the transaction log backup
RESTORE LOG TestDB
FROM DISK = ‘C:\Backups\TestDB_log.bak‘
WITH NORECOVERY;
-- Apply the tail log backup
RESTORE LOG TestDB
FROM DISK = ‘C:\Backups\TestDB_taillog.bak‘
WITH NORECOVERY;
-- Recover the database
RESTORE DATABASE TestDB
WITH RECOVERY;
GO
时间点恢复的最后一个日志备份
有时候,不幸的是,它可能无法执行完全恢复;如果活的事务日志不可用而导致的失败。在这种情况下,我们需要恢复到最近的日志备份的结尾。这是需要准备这种可能性即失败包含事务日志的驱动,这决定了多少次日志备份。如果你需要备份,每15分钟,那么你在15分钟的数据丢失的风险。
想象一下,我们完成了清单5.4中所示的备份序列。对于此演示的缘故,我们覆盖以前的备份文件和备份序列明显缩短要比现实中的。
-- FULL BACKUP at 2AM
USE master ;
BACKUP DATABASE TestDB
TO DISK = ‘C:\Backups\TestDB.bak‘
WITH INIT ;
GO
-- LOG BACKUP 1 at 2.15 AM
USE master ;
BACKUP LOG TestDB
TO DISK = ‘C:\Backups\TestDB_log.bak‘
WITH INIT ;
GO
-- LOG BACKUP 2 at 2.30 AM
USE master ;
BACKUP LOG TestDB
TO DISK = ‘C:\Backups\TestDB_log2.bak‘
WITH INIT ;
GO
如果发生灾难性故障的凌晨2:30分后不久,我们可能需要将数据库还原到它的存在,在日志备份2年底的状态,在凌晨2:30分。
恢复这样的一个例子序列,我们前面看到的很相似,在清单5.3中,但由于尾备份是不可能的,我们只能够恢复到某一点,我们需要使用在
选项,如清单5.5所示。
--RESTORE Full backup
RESTORE DATABASE TestDB
FROM DISK = ‘C:\Backups\TestDB.bak‘
WITH NORECOVERY;
--RESTORE Log file 1
RESTORE LOG TestDB
FROM DISK = ‘C:\Backups\TestDB_log.bak‘
WITH NORECOVERY, STOPAT = ‘Jan 01, 2020 12:00 AM‘;
--RESTORE Log file 2
RESTORE LOG TestDB
FROM DISK = ‘C:\Backups\TestDB_Log2.bak‘
WITH NORECOVERY, STOPAT = ‘Jan 01, 2020 12:00 AM‘;
--Recover the database
RESTORE DATABASE TestDB
WITH RECOVERY;
GO
既然我们已经指定了一个在
在未来的时间里,这段代码将回滚所有完成交易到第二事务日志的结束。
另外,指定一个可能在
时间,属于记录在一个特定的日志文件的交易时间范围。在这种情况下,数据库将恢复到上次提交的事务在规定时间。这是有用的当你知道你要恢复到什么时候,但不知道什么是日志备份包含时间。
它也可以恢复到一个特定的标记的事务。这是非常有用的,例如,你需要恢复多个数据库,通过一定的程序访问,在逻辑上一致的点。这个话题不在这里进一步讨论,但你可以找到更多关于图书在线(http://msdn.microsoft.com/en-us/library/ms187014.aspx),和Mladen prajdic提供了一个很好的例子:http://weblogs.sqlteam.com/mladenp/archive/2010/10/20/sql-server-transaction-marks-restoring-multiple-databases-to-a-common.aspx。
恢复“坏交易”之后
对任何数据库故障的情况之外,可能需要恢复数据库备份,加上事务日志,以一个数据库返回到时间就在一个错误的数据修改了某个特定的点,如删除或截断表。
你这种情况的反应将取决于问题的性质。如果可能的话,你可能会从数据库断开所有用户(在通知他们),并评估刚刚发生了什么事的影响。在某些情况下,您可能需要估计问题发生然后完全恢复的数据库和日志的时间点恢复时间。一旦恢复了,你要通知用户一些交易可能已经丢失,并请求原谅。
当然,你经常不能够以这种方式中断正常的业务操作,解决一个意外的数据丢失。由于实时数据库仍然正常运行和访问,你可以尝试恢复数据库的备份备用物品
模式。这允许进一步的日志备份来恢复但不像使用时使用NORECOVERY
,数据库仍然是可读的。还原方案可能看起来像这样:
- 恢复数据库备份,在
备用物品
模式,与实时数据库 - Roll the logs forward to the point just before the bad transaction occurred, and data was lost.
- Copy the lost data across to the live database and drop the restored copy
Of course, this process is not necessarily straightforward, and can be quite time-consuming. Unless you‘ve purchased a specialized log reading tool, and can interrogate the log backup directly, rolling the logs forward can mean a series of painstaking steps involving restoring a log, checking the data, restoring a bit further, and so on, until you‘ve worked out exactly where the bad transaction occurred. 3步是困难的,因为你将引入数据到现场系统与数据库的当前状态必然是不一致的,所以可以参照完整性问题。
让我们在执行步骤1和2以上,看一个例子。首先,让我们再从头开始运行createandpopulatetestdb.sql脚本来创建其中
数据库,并插入10行测试数据到一个新的logtest表在清单5.6中,我们简单的做一个完整的数据库备份(覆盖任何以前的备份文件)。您需要创建的“备份”目录,如果你没有这样做,或适当调整路径。
-- full backup of the database BACKUP DATABASE TestDB TO DISK =‘C:\Backups\TestDB.bak‘ WITH INIT; GO
清单5.6:TestDB的完全备份
然后,我们将一个新的数据行插入到LogTest表中
USE TestDB
GO
INSERT INTO [TestDB].[dbo].[LogTest]
([SomeInt]
,[SomeLetters2])
VALUES
(66666,
‘ST‘)
SELECT * FROM dbo.LogTest
所以现在我们有一个活其中
11数据库中的行logtest表,以及备份与10行版本。现在让我们来捕获日志备份额外的修饰,如清单5.8所示。
USE master
GO
BACKUP Log TestDB
TO DISK =‘C:\Backups\TestDB_log.bak‘
WITH INIT;
GO
现在,我们要模拟一个错误的“糟糕的交易”,简单地把<em>logtest</em>表,之后我们做的最后一个日志备份。
USE TestDB
GO
DROP TABLE dbo.LogTest ;
USE master
GO
BACKUP Log TestDB
TO DISK =‘C:\Backups\TestDB_log2.bak‘
WITH INIT;
GO
为了试图找回丢失的数据,在不中断业务的正常运行,我们将恢复的副本其中
数据库备用物品
模式。的备用数据库的数据文件和日志文件,称为ANewTestDB,移动到“待机”目录(你需要事先创建这个目录)。
-- restore a copy of the TestDB database, called
-- ANewTestDB, in STANDBY mode
USE master ;
GO
RESTORE DATABASE ANewTestDB
FROM DISK =‘C:\Backups\TestDB.bak‘
WITH STANDBY=‘C:\Backups\ANEWTestDB.bak‘,
MOVE ‘TestDB_dat‘ TO ‘C:\Standby\ANewTestDB.mdf‘,
MOVE ‘TestDB_log‘ TO ‘C:\Standby\ANewTestDB.ldf‘
GO
我们现在有一个新的数据库,称为新的<em>库</em>
,和它的“待机/只读”模式,如图5.1所示。
一个查询logtest
表中anewtestdb数据库将显示10行。然而,我们想把表回状态是在之前它被错误地下降。因此,下一步是执行还原日志备份到备用数据库。
USE master
GO
RESTORE LOG ANewTestDB
FROM DISK = ‘C:\Backups\TestDB_log.bak‘
WITH STANDBY=‘C:\Backups\ANewTestDB_log.bak‘
在这一点上,查询<em>anewtestdb</em>显示11行,我们现在可以将数据重新进入实时数据库。如果我们更进了一步,恢复第二日志备份,我们意识到我们已经走得太远了,表会丢失在备用数据库以及。
另一个做备用恢复是考虑使用第三方工具如红色的门SQL虚拟还原,这一方式来安装备份为生活提供全功能的数据库,没有身体的恢复。
无论他们喜欢与否,开发商经常访问生产数据库来完成特定数据负载和变化。这是DBA和开发人员的共同责任,确保顺利进行,所以不会造成需要的这种行动只是描述问题。我们回到这个话题,后来在<strong>6级处理批量操作</strong>。
当然,所需的修复作用的确切性质取决于糟糕的交易性质。如果一个表是“不小心掉了”,那么很有可能你会走的恢复
与
备用物品
路线。在其他时候,你可能会去做一个简单的脚本来“逆淘汰”的流氓的修改。
如果伤害只会影响单柱或有限数量的行,那么它是可能的,作为一种替代方法,使用的工具,如SQL数据的比较,可以比较直接的备份文件,可以做行级恢复。
或者,如果你运行SQL Server 2005企业版(或以后),和提供最近的数据库快照,您可以运行一个对快照查询来检索数据,它看了看时间数据库快照拍摄,然后写一个更新
或插入
命令将数据从数据库快照到现场,源数据库。
最后,作为最后的手段,一个专门的日志读取器工具可以帮助你扭转了影响交易的虽然我不知道有任何可靠地工作在SQL Server 2005及以后。
概要
在这个层面上,我们已经备份和恢复日志文件的数据库操作的基本知识全部
恢复模式,这将对许多生产数据库规范。
对于大多数数据库管理员,需要执行时间点恢复是一种罕见的事件,但它是一个任务,如果有必要的话,它绝对是至关重要的,它是做的,做的很好;DBA的声誉取决于它。
在腐败案件的驱动器故障,等等,时间点恢复可能涉及,如果你幸运的话,备份尾事务日志和恢复到故障点的权利。如果事务日志不可用,或者如果你恢复以恢复到某个时间点,一个“坏交易”发生之前,那么情况就变得比较复杂,但希望一些覆盖在这一步的技术将帮助。