SQL Server 2005 事务日志之物理体系(三)

事务日志物理体系结构:

物理结构就是我们肉眼看的到的.ldf文件,看不见的应该去医院做下诊断,当然更详细的物理结构我们肉眼看不到。

回归正题:上一篇博文里讲叙到日志记录就好比信用卡的交易记录一样,只不那也是虚拟化的,现在我们把那些记录映射到具体的物体上。假如我有一个习惯-记账,我把那边的2笔信用卡交易记录写到我的账本上.
2011-11-01 12:00:00 支出1200 RMB
2011-11-01 12:30:00 支出10 RMB
既然写在了本子上, 那么我们眼睛能看到了。现在可以说从物理上来说, 日志记录就跟我们记账的明细一样,有效的存储在账本上。

Database Engine 在内部会将每一个物理日志文件分成多个虚拟日志文件。这些虚拟文件没有固定大小,而且物理文件包含虚拟日志文件的数量不固定,这些都是创建日志文件,扩展日志文件的时候Database Engine动态分配的。数据库引擎 尝试维护少量的虚拟文件。在扩展日志文件后,虚拟文件的大小是现有日志大小和新文件增量大小之和。管理员不能配置或设置虚拟日志文件的大小或数量。虚拟日志文件的较小的size和growth_increment会影响系统性能数据库启动,日志备份,及还原的速度(主要是因为会创建更多的虚拟日志文件)。建议为日志文件指定一个与最终所需大小接近的 size 值和一个相对较大的 growth_increment 值(这个可以根据表内数据数量,再加上对时间的评估,如每天的数据多少,每个月的数据多少,根据这个几乎可以确定最终数据库的大小)。

虚拟日志文件就好比账本的数量,一次买个1000页的账本,与10个100页的账本, 明显1000页的容易维护。页数太少了,10天半个月就要去买个,多麻烦。下面创建个测试库,了解下虚拟日志。

CREATE DATABASE [Echo] ON  PRIMARY 
( NAME = N'Echo', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\DATA\Echo.mdf' , SIZE = 3072KB , FILEGROWTH = 1024KB )
 LOG ON 
( NAME = N'Echo_log1', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\DATA\Echo_log1.ldf' , SIZE = 3072KB , FILEGROWTH = 10%), 
( NAME = N'Echo_log2', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\DATA\Echo_log2.ldf' , SIZE = 3072KB , FILEGROWTH = 10%)
GO
use Echo;
go
dbcc loginfo;
go

结果:


FileId为2,3分别代表着Echo_log1,Echo_log2。对应每个物理日志文件ID有4条记录,对应着4个虚拟日志文件。因为对这两个文件初始大小,增量完全一样,所以虚拟日志文件数量也是一样的。我们试着把日志初始大小以及增量设置为更大的值,再对比下虚拟日志文件,运行以下语句创建一个200M的数据文件,2个1G的日志文件:

use master;
go
drop database Echo;
go
CREATE DATABASE [Echo] ON  PRIMARY 
( NAME = N'Echo', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\DATA\Echo.mdf' , SIZE = 204800KB , FILEGROWTH = 1024KB )
 LOG ON 
( NAME = N'Echo_log1', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\DATA\Echo_log1.ldf' , SIZE = 1048576KB , FILEGROWTH = 10%), 
( NAME = N'Echo_log2', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\DATA\Echo_log2.ldf' , SIZE = 1048576KB , FILEGROWTH = 10%)
GO
use Echo;
go
dbcc loginfo;
go


可以看到有16个虚拟日志文件,而且每个FileSize都挺大的,因为日志文件足够大,如果业务系统活动量不多的话,这些日志一年都不一定能填满,也就不会新增的虚拟日志文件。

事务日志是一种回绕的文件,也就是说并不是所有的日志记录一直按顺序排列下去,在创建数据时,逻辑日志文件从物理日志文件的始端开始。新日志记录被添加到逻辑日志的末端,然后像物理日志的末端扩张。若进行截断操作,虚拟日志中最小恢复日志序列号 (MinLSN) 之前的日志记录会被删除。示例数据库中的事务日志的外观与下图所示相似。

再拿账本举例吧,一本账本的页数就好比一个物理日志文件,从第1页起就是物理日志文件的始端,假如第1页至20页是一个虚拟日志文件,那么记账的记录就是从第1页第1条记录,第1页第2条这样排列下去,当第一页记录不下了,就会从第1页的末端后开始,也就是第2页第1条记录开始排列。

当逻辑日志的末端到达物理日志文件的末端时,新的日志记录将回绕到物理日志文件的始端。也就说我记录记到最本子最后一页最后一条记录,再也容不下其他记录,那么就会把第1页某些记录给檫掉, 试想我用铅笔记账,那么用橡皮把第一页的记录给檫掉,那么我就可以重新在第1页记账了,这样岂不节约了钞票,就跟节省了硬盘空间一个道理。当然只有截断了日志才会进行回绕。这个循环可以不断重复,只要逻辑日志的末端不到达逻辑日志的始端。一辈子都账都可以记在一个本子上,够节约了。微软的这种事务日志机制真的不错。

如果经常截断旧的日志记录,始终为到下一个检查点前创建的所有新日志记录保留足够的空间,则日志永远不会填满。但是,如果逻辑日志的末端真的到达了逻辑日志的始端,将发生以下两种情况之一:
1 启用FILEGROWTH ,且磁盘有可用空间, 那么文件就会按指定的增量扩展
2 未启用FILEGROWTH  或者保存日志文件的磁盘的可用空间比日志文件的 growth_increment 中指定的数量少,则会出现 9002 错误。

如果日志包含多个物理日志文件,则逻辑日志在回绕到首个物理日志文件始端之前,将沿着所有物理日志文件移动。

参考自:ms-help://MS.SQLCC.v9/MS.SQLSVR.v9.zh-CHS/udb9/html/36d7f140-b46a-4b1b-81a5-a2e2dddf88c6.htm
http://blog.chinaunix.net/space.php?uid=23929779&do=blog&id=349989

原文地址:https://www.cnblogs.com/itboyblog/p/2264773.html