Quantcast
Channel: CodeSection,代码区,SQL Server(mssql)数据库 技术分享 - CodeSec
Viewing all articles
Browse latest Browse all 3160

SQL Server中事务日志管理的步骤,第5级:完全恢复模式管理日志(译)

$
0
0

SQL Server 中事务日志管理的步骤,第 5 级:完全恢复模式管理日志

作者: Tony Davis , 2012/01/27

系列

本文是进阶系列的一部分: SQL Server 中事务日志管理的步骤

当事情进展顺利时,无需特别注意事务日志的作用或工作方式。您只需要确信每个数据库都有正确的备份机制。当出现问题时,了解事务日志对于采取纠正措施很重要,特别是在需要紧急恢复数据库的时间点时!Tony Davis给出了每个DBA都应该知道的正确的细节级别。

在此级别中,我们将回顾在完全恢复模式下工作时进行日志备份的原因和方法,以及如何使用这些日志备份文件以及完整的数据库备份执行数据库还原。完全恢复模式支持将数据库还原到可用日志备份中的任何时间点,并且假设可以进行尾日志备份,直到发生故障之前最后一次提交事务的时间为止。

什么会被记录?

在完全恢复模式下,将完全记录所有操作。对于插入、更新和删除操作,这意味着对于修改的每一行,都会有一个日志记录,描述执行语句的事务的ID、事务开始和结束时、哪些页已更改、所做的数据更改等。

在完全恢复模式下工作时,可以最低限度地记录的操作(选择进入、大容量插入和创建索引)仍然完全记录,但执行方式略有不同。受这些操作影响的行不是单独记录的;而是在数据库页被填充时只记录它们。这减少了对此类操作的日志记录,同时确保仍然存在执行回滚、重做和时间点还原所需的所有相同信息。Kalen Delaney已经发布了一些关于select into()和index rebuild()操作的日志调查,包括完整和批量日志恢复模式。在大容量日志记录模式下工作时,最小日志记录操作的日志记录差异将在第6级-在大容量日志记录恢复模式下管理日志中进行更详细的讨论。 http://sqlbog.com/blogs/kalen_delaney/archive/2011/03/15/what-gets-logged-for-select-into.aspxhtp://sqlbog.com/blogs/kalen_delaney/archive/2011/03/08/what-gets-logged-for-index-rebuilds.aspx

为什么备份事务日志?

在完全恢复模式下,只有日志备份才能导致日志截断。因此,事务日志将保存自上次备份事务日志以来执行的事务的完整记录。由于所有操作都已完全记录,因此在繁忙的系统中,日志文件可能会增长得非常大、非常快。

因此,在完全恢复模式下工作时,除了执行完全备份和(可选)差异备份之外,还必须执行常规事务日志备份。许多新手或兼职DBA在其数据库上执行完整备份,但不执行事务日志备份。因此,事务日志不会被截断,并且会不断增长,直到它所在的驱动器耗尽磁盘空间,导致SQL Server停止工作。

在执行日志备份后,会立即截断日志,前提是自上次备份以来已发生检查点,并且没有其他因素会延迟截断,例如数据备份或还原操作。有关可能延迟截断可恢复VLF的因素的完整列表,以及保持大量日志活动的因素(否则不需要),如恶意、长时间运行的未提交事务或数据库镜像或复制进程,请参阅: http://msdn.microsoft.com/en-gb/library/ms345414.aspx 。

仅复制事务日志的备份

只复制事务日志的备份不会截断事务日志。仅复制日志备份与正常日志备份方案“独立”存在;它不会中断日志备份链。

简而言之,事务日志备份的双重目的是允许恢复和恢复到以前的时间点,并控制事务日志的大小。与事务日志相关的问题最常见的原因可能是在完全恢复模式下工作,而不是简单地进行日志备份,或者不经常进行日志备份以控制事务日志文件的大小。

如果您不确定是否在给定的数据库上执行事务日志备份,那么您可以使用类似于列表5.1所示的查询,简单地查询msdb数据库中的backupst表。

USEmsdb ; SELECT backup_set_id , backup_start_date , backup_finish_date , backup_size , recovery_model , [type] FROM dbo.backupset WHERE database_name ='TestDB'

列表 5.1 :是否正在进行日志备份?

在类型列中,D表示数据库备份,L表示日志备份,I表示差异备份。

请注意,由于可以在不影响备份和还原行为的情况下操作此backupset表中的数据,因此您可能希望通过查询sys.database_recovery_status来验证此查询的结果,以查看最后一个log_backup_lsn的值(请参见列表3.5),或查看sys.databases表以查看log_reuse_wait_desc的值(将返回如果需要备份,则返回urn log_backup)。

如何备份事务日志

如前所述,不首先进行至少一次完整备份,就不可能执行事务日志备份。实际上,如果您有一个处于完全恢复模式但从未备份过的数据库,那么它实际上不会在完全恢复模式下工作。在执行第一次完全备份之前,数据库将处于自动截断模式。

所有数据库备份(完整、日志或其他)都使用backup命令执行。该命令接受许多选项,这些选项记录在下面: http://msdn.microsoft.com/en-us/library/ms186865.aspx 。但是,在最基本的情况下(通常是这样使用的),执行磁盘完全备份的命令如下:

BACKUP DATABASE DatabaseNameTO DISK ='FileLocation\DatabaseName.bak';

如果这是要执行的第一次备份,则将在指定目录中创建databasename.bak文件。如果这样的文件已经存在,那么默认行为是将后续备份附加到该文件。要覆盖此行为并规定应覆盖任何现有文件,可以使用init选项,如下所示:

BACKUP DATABASE DatabaseNameTO DISK ='FileLocation\DatabaseName.bak'WITH INIT;

但是,最常见的情况是,每个后续备份都有一个唯一的名称;在接下来的部分中,将详细介绍恢复到故障点。

在每次常规(如每日)完全备份之后,都会有频繁(如每小时)的日志备份,其基本命令非常类似:

BACKUP LOG DatabaseNameTO DISK ='FileLocation\DatabaseName_Log.bak';

存储日志备份

显然,备份的数据和日志文件不应存储在承载实时文件的同一驱动器上。如果该驱动器出现硬件故障,那么您的所有副本以及活动文件都将丢失,备份将是徒劳的。文件应备份到单独的设备,或备份到本地镜像驱动器。

日志备份频率

如前几级所述,您可能每15分钟进行一次日志备份,甚至可能更频繁。在这种情况下,为了避免需要恢复大量的事务日志文件,您可以选择采用一种备份方案,该方案包括完整备份和差异备份,以及事务日志备份。

事实上,备份方案往往是在理想和实际之间、对数据丢失的真实风险的评估与公司将付出的代价以及降低风险所涉及的成本之间进行折衷。许多非常重要的业务应用程序使用的备份方案都比较简单,但也比较严格,可能包括定期的夜间完整备份和每小时事务日志备份。

日志备份的频率也可能由数据库所属的事务数决定。对于非常繁忙的数据库,可能需要经常备份以控制日志的大小。

没有简单的方法来计算日志备份的频率。大多数DBA将对日志备份的频率进行最佳估计,然后观察文件的增长特性,然后根据需要调整备份方案,以防止文件过大。

如何打破日志链

如前所述,如果不首先进行至少一次完整备份,就不可能执行事务日志备份。为了将数据库恢复到某个时间点,或者恢复到特定日志备份的末尾,或者恢复到特定日志备份中的某个时间点,必须存在一个完整的完整的日志记录链,从完整(或差异备份)之后的第一个日志备份到故障点。这就是所谓的日志链。

有很多方法可以破坏日志链,如果这样做,则意味着您只能将数据库恢复到破坏日志链的事件发生之前的日志备份时间。简而言之,如果您关心恢复数据的能力,那么断开链并不是一个好主意。断链最常见的两种方法包括:

事务日志备份文件丢失或损坏

您只能恢复到上一次良好日志备份。日志链将在下一次良好的完整备份或差异备份时重新启动。

切换到 简单恢复模式

如果您从完全恢复模式切换到简单恢复模式,这将破坏日志链,因为将启动检查点,并且可以立即截断事务日志。当且如果您返回到完整模式,则需要进行另一个完整备份以重新启动日志链。实际上,在进行完整备份之前,数据库将保持自动截断模式,并且您将无法备份日志文件。

在SQL Server 2008之前,有两个命令,即backup log with no_log或backup log with truncate_only(它们在功能上是等效的),在发出命令时,会强制截断日志文件,从而中断日志链。在任何版本的SQL Server中都不应该发出这些命令,但我在这里提到这些命令,因为在尝试处理“失控日志文件”时,粗心的人仍然会使用这些命令,而不理解它对他们恢复数据库的能力的影响。请参阅第8级-帮助,我的日志已满,了解更多详细信息。

末尾日志备份

只要您有一个最近的完整备份和一个完整的日志链,您就可以将数据库恢复到在任何失败之前的最终日志备份结束时的状态。但是,假设您每小时进行一次事务日志备份,并且在下午1:45发生故障。您可能会丢失价值45分钟的数据;实际上,如果失败是如此灾难性,以至于实时事务日志无法恢复,那么这就是您将丢失的数据量。

但是,有时即使数据文件不在,实时事务日志仍然可用,特别是当事务日志包含在单独的专用驱动器上时。如果是这种情况,则应备份实时事务日志,即对自上次日志备份以来生成的日志记录执行最终备份。这将捕获活动日志文件中的剩余日志记录,直到出现故障为止。这称为尾日志备份,是在开始恢复和恢复操作之前应执行的最后一个操作。

末尾日志备份和最小日志操作

如果由于数据库故障而导致数据文件不可用,并且日志的尾部包含最少的日志操作,那么就无法进行尾部日志备份,因为这需要访问数据文件中更改的数据扩展数据块。这将在第6级中更详细地介绍,以大容量日志模式管理事务日志。

如果要还原的数据库处于联机状态,则日志的尾部将按以下方式进行备份:

BACKUP LOG DatabaseNameTO DISK ='FileLocation\DatabaseName_Log.bak'WITH NORECOVERY

NORECOVERY选项将数据库置于还原状态,并假定要执行的下一个操作是还原。如果数据库处于脱机状态且无法启动,则仍应尝试按照刚才描述的方式备份日志的尾部(尽管可以省略norecovery选项,因为不会进行任何事务)。

如果您确定日志文件已损坏,文档建议作为最后一种方法,您尝试使用以下方法进行尾日志备份:

BACKUP LOG DatabaseNameTO DISK ='FileLocation\DatabaseName_Log.bak'WITH CONTINUE_AFTER_ERROR

如果主数据库和数据文件已损坏,但日志可用,Microsoft建议重建主数据库,然后备份上一个活动日志。但是,这些主题不在这个进阶的范围内,我将参考文档了解更多的细节。请参阅 http://msdn.microsoft.com/en-us/library/ms190952.aspx 。

执行还原和恢复

在执行了尾日志备份之后,如果可能的话,下一步是还原最后一次完整备份(如果合适,在后面是差异备份),然后还原日志备份文件的完整序列,包括尾日志备份。此还原操作序列的基本语法如下:

RESTORE {DATABASE | LOG} DatabaseNameFROM DISK ='FileLocation\FileName.bak'WITH NORECOVERY;

如果还原时省略WITH NORECOVERY选项,则默认情况下,还原命令将继续进行恢复。换句话说,SQL Server将尝试协调数据和日志文件,前滚已完成的事务,然后根据需要回滚未完成的事务。通过使用norecovery指定,我们将指示SQL Server在执行任何回滚之前,我们正在输入一个还原序列,并且必须前滚更多操作。在还原顺序中还原最后一个备份后,可以按以下方式恢复数据库:

RESTORE DATABASE DatabaseName WITH RECOVERY

一个常见的要求是将数据库还原到不同的位置,在这种情况下,您可以简单地将文件作为还原过程的一部分移动,如下所述: http://msdn.microsoft.com/en-us/library/ms190255.aspx 。

数据库故障后恢复

下面的示例描述了如何恢复数据库以响应故障,从而使数据库数据文件不再可访问。

完全恢复到故障点

假设“实时”事务日志可以在数据库故障(可能由硬件故障引起)后访问,那么理论上,应该可以使用以下步骤恢复和恢复数据库,直至故障点:

1备份日志的尾部

2恢复最新的完整备份(如果适用,还包括差异备份)

3依次还原在完全(或差异)备份之后执行并在失败之前完成的每个事务日志备份。

4恢复尾日志备份

5恢复数据库

联机丛书中的许多示例演示了从“备份集”恢复和恢复,换句话说,是存储所有备份的单个“设备”。实际上,这意味着当备份到磁盘时,备份设备是位于该磁盘上某个位置的单个.bak文件。

因此,例如,列表5.2中所示的简单示例使用由一个完整备份和一个事务日志备份组成的备份集,并演示如何执行完整恢复。为了运行此代码,首先需要重新创建数据库,然后插入一些示例数据行(为了方便起见,此级别的代码下载中包含执行此操作的脚本 CreateAndPopulateTestDB.sql )。您还需要在数据库服务器的本地C盘上创建一个“Backups”目录,或者根据需要修改文件路径。 测试数据库

--执行测试数据库的完整备份 --WITH FORMAT选项启动新的备份集 --小心,因为它将覆盖任何现有集 --完整备份成为集中的第一个文件 BACKUPDATABASETestDB TODISK='C:\Backups\TestDB.bak' WITHFORMAT; GO --对测试数据库执行事务日志备份 --这是集合中的第二个文件 BACKUPLogTestDB TODISK='C:\Backups\TestDB.bak' GO ――…<此处出现故障>… --restore headeronly命令是可选的。 --它只是确认组成 ――当前设置 RESTOREHEADERONLY FROMDISK='C:\Backups\TestDB.bak' GO --备份日志尾部以准备还原 --这将成为备份集的第三个文件 BACKUPLogTestDB TODISK='C:\Backups\TestDB.bak' WITHNORECOVERY; GO --还原完整备份 RESTOREDATABASETestDB FROMDISK='C:\Backups\TestDB.bak' WITHFIL

Viewing all articles
Browse latest Browse all 3160

Trending Articles