SQL Server中的数据库都是由一或多个数据文件以及一或多个事务日志文件组成的。数据库
顾名思意,数据文件主要存储数据库的数据,包括数据库内容结构,数据页,索引页等等。那么事务日志究竟是干什么的呢?它主要是用来保存数据库修改记录的,以下图: ide
SQL Server的工做原理为何这样呢?为何不把数据马上写入数据文件呢?缘由很简单:为了获得更高的效率和性能。数据文件为了适应新的数据可能会扩展,可能会从新分配页,分配新空间等等。而日志都是连续被记录的,因此记录事务日志要快得多。这也就是为何咱们经过推荐把物理磁盘单独划分一区用来存储事务日志的缘由了,这样可使磁盘在读写上最大程序的保持天然连续。数据文件的读写有很大的随机性。布局
那么事务日志到底都存些什么呢?看下面这个很是简单的例子: 性能
在事务日志中,数据变化被记录在一个连续的日志记录中,且每个记录都有一个编号,叫作日志序列编号(Log Sequence Number, LSN)。 spa
在事务日志中,每个日志记录都被存储在一个虚拟日志文件中。事务日志能够有任意多个虚拟日志文件,数量的多少取决于数据库引擎,并且每一个虚拟日志文件的大小也不是固定的。 .net
如上图所示,活动区间(active portion)的日志就是包含咱们事务的区域。这区间就是完整恢复数据库所须要的。当更多的事务被建立时,活动区间的日志也会随着增加。 3d
那么当CheckPoint被执行时,会发生什么变化呢?答案是:全部有变化的数据写到数据文件中,而后建立一个检查点记录(CheckPoint record)。日志
如今。由事务1,2,3所致使的变化将会被写到数据文件中。由于事务3没有被提交,因此活动区间日志的范围变成了从LSN50到LSN52之间。若是使用简单恢复模型的话,那么LSN45到LSN49之间区域能够被重用,由于那些记录已经再也不须要了。 orm
当SQL Server把虚拟日志文件1和2做为可重用区域时,事务日志也相应被截断(Truncate)。须要注意的是,物理日志大小也会随着变更。若是数据库运行在完整或是批量日志恢复模型下,那么从LSN45到49之间的区域将被删除(delete),并且直到事务日志被备份后,这段区域的空间才会被重用。server
那么当更新的事务被建立时,又会发生什么呢?在简单模式下,日志的起始空间将会被重用。
在完整或是批量日志恢复模型下,事务日志的空间则会被扩展。
假如事务日志是一个固定大小的日志,那么在SQL Server2000系统中,你会收到以下错误信息:
Server: Msg 9002, Level 17, State 6, Line 1
The log file for database 'AdventureWorks' is full. Back up the transaction log for the database to free up some log space.
在SQL Server 2005里面,错误会显示为:
Msg 9002, Level 17, State 4, Line 1
The transaction log for database 'AdventureWorks' is full. To find out why space in the log cannot be reused, see the log_reuse_wait_desc column in sys.databases
注意:并非说运行在简单恢复模式下的数据库永远都不会遇到9002的错误。若是你有一个很长的、正在运行的、未提交的事务,那么你的事务日志依然会被填满,由于SQL Server不能删除任何一个已经开始运行以后被建立的日志。也就是说,活动区间里面的日志从事务起始时被记录,而且已经没有活动区间能够被删除或是重用了。
因此,要保持你的事务日志基本处理一个可管理的范围:
为了找出数据库中最起始的活动事务,特别是事务起始时间时,就可使用DBCC OPENTRAN命令,例如:
DBCC OPENTRAN
结果为:
Transaction information for database 'AdventureWorks'.
Oldest active transaction:
SPID (server process ID) : 52
UID (user ID) : 1
Name : user_transaction
LSN : (754:531:1)
Start time : Jul 14 2008 5:43:55:390PM
为了找出每个数据库已经使用的日志空间大小,可使用DBCC SQLPERF命令:
DBCC SQLPERF(LOGSPACE)
为了找出事务日志使用了多少虚拟日志数量,可使用DBCC LOGINFO命令。它显示的细节内容就是你当前所链接数据库的内容,下面就是AdventureWorks数据库的输出:
从上图咱们能够获得以下信息:你的事务日志中有四个虚拟日志文件(一行一个),且全部虚拟日志文件包括在一个单一的物理文件中(FileId=2)。第一,二,三的虚拟日志文件大小是458752比特,最后一个虚拟日志文件的大小是712704比特。1~3虚拟文件历来没有被使用或是重用过(Status=0), 第四个虚拟日志文件正在被使用(Status=2)。虚拟日志文件在物理上的布局具备链接的编号(FSeqNo是递增的), 实际状况可能与此有所不一样。