翻译14

SQL Server中事务日志管理的阶梯,级别1 :事务日志概述

系列

这篇文章是楼梯系列的一部分:SQL服务器中事务日志管理的阶梯

当事情进展顺利时,不需要特别注意事务日志的功能或工作方式。您只需要确信每个数据库都有正确的备份机制。当出现问题时,了解事务日志对于采取纠正措施非常重要,尤其是当迫切需要对数据库进行时间点恢复时!托尼·戴维斯给出了每个DBA应该知道的正确细节级别。

级别1 :事务日志概述

事务日志是一个文件,其中SQL Server存储在与日志文件关联的数据库上执行的所有事务和数据修改的记录。在发生导致SQL Server意外关闭的灾难(例如实例或硬件故障)时,事务日志用于恢复数据库,数据完整性良好。重新启动后,数据库进入恢复过程,在恢复过程中读取事务日志,以确保所有有效的提交数据都写入数据文件(前滚),所有部分未提交事务的影响都被撤消(后滚)。简言之,事务日志是SQLServer确保数据库完整性和事务的ACID属性(尤其是持久性)的基本手段。

DBA在管理事务日志方面的一些最重要职责如下:

·        选择正确的恢复模式–SQL Server提供三种数据库恢复模式:完整(默认)、简单和批量记录。DBA必须根据数据库的业务需求选择合适的模式,然后建立适合该模式的维护程序。

·        执行事务日志备份–除非在简单模式下工作,否则至关重要的DBA定期备份事务日志。一旦捕获到备份文件中,日志记录就可以随后应用于完整数据库备份,以便执行数据库恢复,从而重新创建以前某个时间点存在的数据库,例如就在失败之前。

·        班长管理日志增长–在繁忙的数据库中,事务日志的大小可以快速增长。如果不定期备份,或者大小不合适,或者分配了不正确的增长特征,事务日志文件可能会被填满,导致臭名昭著“9002”(事务日志已满)错误,它使SQL Server进入“只读”模式(如果在恢复过程中发生,则进入“资源挂起”模式)。

·        使最优化日志吞吐量 和可用性–除了进行备份等基本维护之外,DBA还必须采取措施确保事务日志的充分性能。这包括硬件考虑,以及避免日志碎片等可能影响事务性能的情况

在这个楼梯系列中,我们将详细考虑这些核心维护任务中的每一项。在这里,首先,我们将概述SQL Server如何使用事务日志,以及它影响DBA生命周期的两个最重要的方式,即数据库恢复和恢复以及磁盘空间管理。

SQL Server如何使用事务日志

在SQL Server中,事务日志是一个物理文件,通常由扩展名LDF标识,但不是强制标识。它是在创建数据库时自动创建的,并带有通常由MDF扩展名标识的主数据文件,不过也可以使用存储数据库对象和数据本身的任何扩展名。事务日志虽然通常实现为单个物理文件,但也可以实现为一组文件。但是,即使在后一种情况下,SQL Server仍将它视为单个顺序文件,因此SQL Server不能也不会并行写入多个日志文件,因此将事务日志实现为多个文件没有性能优势。这将在中进行更详细的讨论级别7—调整和增长事务日志。

每当T - SQL代码对数据库对象( DDL )或其包含的数据进行更改时,不仅数据文件中的数据或对象会更新,更改的详细信息也会记录为航海日志记录在事务日志中。每个日志记录包含有关执行更改的事务的ID、该事务开始和结束的时间、更改的页面、进行的数据更改等的详细信息。

注:事务日志不是审计跟踪。它不提供对数据库所做更改的审核跟踪;它并不记录对数据库执行的命令,只是记录数据因此而发生的变化。

当进行数据修改时,相关数据页可望从数据高速缓存中读取,或者如果尚未在高速缓存中,则首先从磁盘中检索。在数据缓存中修改数据,并在日志缓存中创建描述事务效果的日志记录。提交事务时,日志记录将写入磁盘上的事务日志。但是,实际更改的数据可能要等到数据库检查点发生。缓存中自从磁盘读取以来已修改的任何页面,使得缓存中的数据值不同于磁盘上的数据值,都称为脏页面。这些脏页可能同时包含以下内容:

·        已提交并“硬化”到事务日志文件但尚未提交到数据文件的数据

·        由未结交易修改的数据,即尚未提交(或回滚)的数据

定期数据库检查点进程扫描数据缓存并将所有脏页刷新到磁盘,此时修改将反映在物理数据文件和日志文件中。即使在交易仍未完成的情况下也是如此;在检查点期间,与打开的事务相关的脏页被刷新到磁盘,SQL Server始终确保与这些打开的事务相关的日志记录在脏页刷新到数据文件之前从日志缓存刷新到事务日志文件。

注:另一个扫描数据缓存的进程LazyWriter也可能在检查点之外将脏数据页写入磁盘,如果由于内存压力而被迫这样做的话。

这里需要注意的重要一点是,日志缓冲区管理器始终保证在将数据页写入物理数据文件之前,将更改描述(日志记录)写入磁盘上的事务日志。这种机制被称为预写测井。它本质上是SQL Server确保事务持久性的机制(请参见酸性数据库事务)。

通过始终先将更改写入日志文件,SQL Server具有一种机制的基础,该机制可以保证所有提交的事务的效果最终将反映在数据文件中,并且源自不完整事务的磁盘上的任何数据修改,即那些既没有提交也没有回滚的数据修改最终不会反映在数据文件中。

如果数据库崩溃,例如,在提交某个事务( T1 )之后,但在将受影响的数据写入数据文件之前,则在重新启动时数据库恢复过程启动,尝试协调事务日志文件和数据文件的内容。它将读取事务日志文件,并确保记录在日志文件中的包括事务T1的所有操作都“前滚”( redone ),以便它们反映在数据文件中。

同样,在数据库崩溃后,恢复过程将通过从日志文件中读取相关操作并对数据执行反向物理操作来“回滚”(撤消)数据库中与未提交事务相关联的任何数据更改。

这样,SQL Server可以在发生崩溃时将数据库恢复到一致状态。更一般而言,如果出现以下情况,则会发生回滚(撤消)过程:

·        为显式事务发出回滚命令

·        出现错误,XACT _ ABORT已打开

·        如果数据库检测到数据库和发起事务的客户端之间的通信中断。

在这种情况下,读取与中断的事务有关的日志记录,或者明确发出回滚命令的日志记录,并回滚更改。通过这些方式,SQLServer可以确保与事务相关联的所有操作作为一个单元成功,或者全部失败。因此,事务日志代表了SQLServer在正常日常操作中确保数据一致性和完整性的基本手段之一。

然而,事务日志起着另一个重要的作用,因为它提供了数据库的机制修复在灾难发生时,恢复到先前的时间点。通过适当的规划和管理,您可以使用这些日志文件的备份将所有数据恢复到损坏或不可用的程度。

事务日志和数据库还原

如前所述,事务日志文件存储一系列日志记录,这些记录根据事务启动的时间顺序排列,提供针对该数据库发布的修改和事务的历史记录。每个日志记录包含有关执行更改的事务的ID、该事务开始和结束的时间、更改的页面、进行的数据更改等的详细信息。事务日志文件中的日志记录被组织成多个部分,称为虚拟日志文件( VLFs )—这些将在中详细介绍水平2–事务日志体系结构

SQL Server的预写日志记录机制保证了修改的描述(即日志记录)将在修改的数据本身写入数据文件之前写入VLF。因此,日志记录可能包含已关闭(已提交)事务或打开(未提交)事务的详细信息,并且在每种情况下,由事务修改的数据可能已经写入数据文件,也可能没有写入数据文件,这取决于是否出现检查点。

注:通过定期将脏页从缓存刷新到磁盘,数据库检查点进程控制SQL Server在数据库恢复操作期间需要执行的工作量。如果SQL Server不得不将大量与脏页相关的提交事务的更改前滚,则恢复过程可能非常漫长。

在恢复过程中,回滚操作可能需要与开放事务相关的任何日志记录,并且这些日志记录将始终是所谓的活跃的VLF,并将始终保留在日志文件中。与已关闭的事务相关的日志记录也将是活动VLF的一部分,直到达到在整个VLF中没有与打开的事务相关联的日志记录的点,此时VLF变为不活动的

这些非活动VLF中的日志记录基本上提供了先前完成的数据库事务的“历史”,这些非活动VLF的情况因数据库的恢复模式而异。我们将在此楼梯的3 - 6层详细讨论这些恢复模式,但这里的关键点是,如果您使用的是完整(或大容量日志)数据库恢复模式,则事务日志将日志记录保留在非活动VLFs中,直到进行日志备份(稍后将详细介绍)。

通过备份事务日志,我们可以将实时日志中的所有日志记录(包括这些非活动VLFs中的日志记录)捕获到备份文件中。然后可以使用这些日志备份将数据库恢复到以前的时间点;希望是一个非常接近“灾难”发生点的时间点。如果发生这样的灾难,日志备份文件可以应用于完整数据库备份文件的恢复副本,并且在完整备份之后发生的任何事务都将在数据库恢复期间“前滚”,以恢复数据库并将数据恢复到给定的时间点,从而最大限度地减少数据丢失。当然,这是假设您不仅进行了这些日志备份,还将它们转移到了安全位置。如果日志备份文件与实时日志文件位于同一驱动器上,并且该驱动器崩溃,则可能会丢失所有备份。

当数据库处于简单恢复模式时(更多信息参见第3层和第4层),活动VLFs中的日志记录将被保留,因为回滚操作可能需要这些日志记录。但是,非活动VLFs将缩短了的当出现检查点时,这意味着这些VLFs中的日志记录可以立即被新的日志记录覆盖。这就是为什么在简单恢复中操作的数据库被称为自动截断模式。在此模式下,日志中不维护“历史记录”,因此无法在日志备份中捕获它并将其用作恢复过程的一部分。

控制日志文件的大小

希望前面的讨论已经表明,对于大多数以完全恢复模式运行的生产数据库,需要定期备份事务日志文件,以便能够将数据库恢复到特定的时间点。

但是,在完全(或BULK _ LOGGED )模式下操作时,有第二个重要原因需要进行这些日志备份,那就是控制日志的大小。请记住,对于修改SQL Server数据库中的数据或对象的每个事务,日志记录都会写入日志文件。在一个繁忙的系统中,有许多并发事务,或写入大量数据的事务,事务日志的大小会快速增长。

在完全(或BULK _ LOGGED )模式下工作时,在备份文件中捕获非活动VLFs中的日志记录副本是使这些VLFs符合截断条件的唯一操作,这意味着日志记录占用的空间变得可重用。

关于截断和事务日志大小的简要说明:常见的误解是截断日志文件意味着日志记录被删除,文件大小减小。没有;截断日志文件只是将空间标记为可重用的行为。在每个不同恢复模型的上下文中,截断将在后续级别中进行更详细的讨论。

因此,在完全(或BULK _ LOGGED )模式下工作时执行定期事务日志备份至关重要的原因之一是控制日志的大小。

备份事务日志的简单示例

为了简要说明我们在第一层中讨论的一些概念,我们将通过一个非常简单的例子来说明如何为在完全恢复模式下运行的数据库备份事务日志。每个单独进程和命令的细节将在后续级别中更详细地介绍。

在清单1.1中,我们在SQL Server 2008实例上创建了一个新的TestDB数据库,然后使用DBCC SQLPERF ( LOGSPACE )命令立即获得日志文件的大小。

USE master ;IF EXISTS ( SELECT  name
            FROM    sys.databases
            WHERE   name = 'TestDB' ) 
    DROP DATABASE TestDB ;CREATE DATABASE TestDB ON(
  NAME = TestDB_dat,
  FILENAME = 'C:\Program Files\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\Data\TestDB.mdf') LOG ON(
  NAME = TestDB_log,
  FILENAME = 'C:\Program Files\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\Data\TestDB.ldf') ;DBCC SQLPERF(LOGSPACE) ;Database Name     Log Size (MB) Log Space Used (%) Status---------------------------------------------------------
master            1.242188      34.27673           0...<snip>...
TestDB            0.9921875     31.74213           0

清单1.1 :新的初始日志文件大小测试数据库资料库

如您所见,日志文件当前的大小约为1mb,大约30 %已满。

注:在实例上创建的用户数据库的初始大小和增长特征由模型数据库的属性决定,每个数据库将使用的默认恢复模型也是如此(在本例中为FULL )。我们将在中更详细地讨论这些属性的影响级别7—调整和增长事务日志

文件的大小可以通过简单地在磁盘上定位物理文件来确定,如图1.1所示。

图1.1 :的数据和日志文件测试数据库

现在,我们执行的数据文件备份测试数据库,如清单1.2所示(首先需要创建“备份”目录)。请注意,此备份操作可确保数据库真正在完全恢复模式下运行;更多关于这个水平3–交易logs、备份和恢复

-- full backup of the databaseBACKUP DATABASE TestDBTO DISK ='C:\Backups\TestDB.bak'WITH INIT;
GO

清单1.2 : TestDB的初始完整备份

由于此备份操作,数据或日志文件的大小或使用的日志空间百分比没有变化,这可能并不令人意外,因为数据库中没有用户表或数据。让我们纠正这个错误,在这个数据库上创建一个名为LogTest的表,用100万行数据填充它,并重新检查日志文件大小,如清单1.3所示。这个脚本的作者是杰夫·摩登,经常在sqlservercentral .com论坛上看到,并在他的善意许可下被转载。不要担心代码的细节;这里唯一重要的是我们插入了很多行。这段代码可能需要几秒钟才能在您的机器上执行,这并不是因为代码效率低;所有的工作都在幕后进行,写入数据和日志文件。

USE TestDB ;
GOIF OBJECT_ID('dbo.LogTest', 'U') IS NOT NULL 
    DROP TABLE dbo.LogTest ;--===== AUTHOR: Jeff Moden--===== Create and populate 1,000,000 row test table.-- "SomeID" has range of 1 to 1000000 unique numbers-- "SomeInt" has range of 1 to 50000 non-unique numbers-- "SomeLetters2";"AA"-"ZZ" non-unique 2-char strings-- "SomeMoney"; 0.0000 to 99.9999 non-unique numbers-- "SomeDate" ; >=01/01/2000 and <01/01/2010 non-unique-- "SomeHex12"; 12 random hex characters (ie, 0-9,A-F) SELECT TOP 1000000
        SomeID = IDENTITY( INT,1,1 ),
        SomeInt = ABS(CHECKSUM(NEWID())) % 50000 + 1 ,
        SomeLetters2 = CHAR(ABS(CHECKSUM(NEWID())) % 26 + 65)
        + CHAR(ABS(CHECKSUM(NEWID())) % 26 + 65) ,
        SomeMoney = CAST(ABS(CHECKSUM(NEWID())) % 10000 / 100.0 AS MONEY) ,
        SomeDate = CAST(RAND(CHECKSUM(NEWID())) * 3653.0 + 36524.0 AS DATETIME) ,
        SomeHex12 = RIGHT(NEWID(), 12)INTO    dbo.LogTestFROM    sys.all_columns ac1
        CROSS JOIN sys.all_columns ac2 ;DBCC SQLPERF(LOGSPACE) ;

清单1.3 :在日志测试表中插入一百万行测试数据库

请注意,日志文件大小已膨胀到将近110 MB,日志已满91 % (系统上的数字可能略有不同)。如果我们要插入更多的数据,它将不得不再次增大大小以容纳更多的日志记录。同样,可以从物理文件中确认大小增加(数据文件已增长到64mb )。

此时,通过重新运行清单1.2,我们可以再次备份数据文件,它不会影响日志文件的大小,也不会影响文件中使用的空间百分比。但是,现在我们备份事务日志文件并重新检查这些值,如清单1.4所示。

-- now backup the transaction logBACKUP Log TestDBTO DISK ='C:\Backups\TestDB_log.bak'WITH INIT;
GODBCC SQLPERF(LOGSPACE) ;Database Name   Log Size (MB) Log Space Used (%) Status-------------------------------------------------------
master          1.242188      63.52201           0...<snip>
TestDB          99.74219      6.295527           0

清单1.4 :备份的事务日志测试数据库

日志文件仍然是相同的物理大小,但是通过备份文件,SQL Server能够截断日志,使得日志文件中“非活动”VLFs中的空间可以重用;可以添加更多日志记录,而不需要物理增长文件。当然,我们还将日志记录捕获到备份文件中,因此如果需要恢复测试数据库数据库恢复到以前的状态。

总结

在第一层中,我们介绍了事务日志,并解释了SQL Server如何通过预写日志机制来维护数据一致性和完整性。我们还介绍并简要演示了DBA如何将事务日志文件的内容捕获到备份文件中,然后作为恢复过程的一部分重新使用备份文件来恢复数据库。最后,我们强调了备份在控制事务日志大小方面的重要性。

在下一个级别,我们将更仔细地了解事务日志的体系结构。

 

 

猜你喜欢

转载自blog.csdn.net/xtt_3170707038/article/details/80721294