今天我想谈下SQL Server里的一个特别话题——即时文件初始化(Instant File Initialization)。对于你的SQL Server实例,如果你启用了即时文件初始化,在特定情况下,你会获得巨大的性能提升。即时文件初始化定义了当在数据文件里分配新的空间时,SQL Server引擎如何和Windows操作系统打交道。
问题缘由
在SQL Server默认配置里,当你在数据文件里分配新空间时,SQL Server会调用内部WIN32 API函数,填0初始化新分配的NTFS簇。这就是说新分配的空间的每个字节会用0值(0x0)重写。这个举动会阻止访问到原始数据问题,即在同个NTF簇里物理存储的数据。在下列SQL Server操作中,会发生填0初始化:
创建新的数据库
数据库自动增长
数据库备份还原
当你创建10GB的数据库文件,SQL Server第1步需要把10GB的数据块写上0值。这个会花费很长时间。我们来看下面CREATE DATABASE语句:
1 -- Create a new 10 GB database 2 CREATE DATABASE TestDatabase ON PRIMARY 3 ( 4 NAME = N'TestDatabase', 5 FILENAME = N'D:\SQL\DATA\TestDatabase.mdf' , 6 SIZE = 10240000KB , 7 FILEGROWTH = 1024KB 8 ) 9 LOG ON 10 ( 11 NAME = N'TestDatabase_log', 12 FILENAME = N'D:\SQL\Log\TestDatabase_log.ldf' , 13 SIZE = 1024KB , 14 FILEGROWTH = 10% 15 ) 16 GO |
从代码可以看到,这里我创建10GB的数据库文件。在我SQL Server默认配置里,这个语句花费了近49秒,因为SQL Server通过WIN32 API函数写入10GB的0到存储。假设你有损坏的数据库(例如也是10GB),你想还原备份,会发生什么?在第1步通常人们会怎么做?是会删除损坏的数据库。这意味这你的数据库文件没了,在还原文件操作期间,SQL Server第1步需要重建文件。
SQL Server第1步创建10GB“空”的数据库,在NTF文件系统里数据文件会被填0初始化。
最后1步备份被还原时,SQL Server再次写入10GB的数据到数据文件。
你会发现,你写了近20GB的数据到你的存储!如果你在现存的文件上还原你的备份,SQL Server会跳过第1步,直接写入10GB的数据到你的存储——你就获得了100%的性能提升!
即时文件初始化
如果你不想SQL Server进行你数据文件的填0初始化,你可以重新配置SQL Server。如果你授权SERVICE帐号,在对应运行的SQL Server下——执行卷维护任务(Performance Volume Maintenance Task)特权,在你重启SQL Server后,SQL Server会跳过数据文件的填0初始化。我曾说过这只对数据文件有效——在SQL Server里日志文件还是总要填0初始化的!这是米有办法滴!!!如果日志文件没有填0初始化,当日志文件被包裹时,故障还原进程就不知道从哪里结束。故障还原停在它找到下条日志记录需要处理头部0值地方。
你可以通过secpol.msc对SQL Server的SERVICE帐号授予执行卷维护任务(Performance Volume Maintenance Task)特权。
在重启后,SQL Server现在可以跳过数据文件的填0初始化。当我再次执行CREATE DATABASE,它只花费了近210ms——那是巨大的区别!副作用呢?你可以通过DBCC PAGE命令获得在分配的NTFS簇里存储的原始内容:
1 -- Enable DBCC trace flag 3604
2 DBCC TRACEON(3604)
3 GO
4
5 -- Dump out a page somewhere in the data file
6 -- A hex dump is working here
7 DBCC PAGE (TestDatabase, 1, 1000, 2)
8 GO
你看到我在我的数据文件里随便倾倒出了一个页。在那个情况下,SQL Server现在就会返回你一些垃圾数据——在新分配的NTFS簇里先前存储的数据——对SQL Server毫无关联的数据。
通过对SQL Server授予这个权限,基本上你打开了一个安全漏洞:用户(有正确权限的)可以获得老数据,在文件系统里先前存储的。因此对此你必须要仔细考虑下,对SQL Server是否要授予这个特权。
如果你想知道,你的SQL Server是否带这个权限在运行,你可以启用3004和3605跟踪标记。用这些启用的跟踪标记,SQL Server在错误日志会报告那个文件被填0初始化。接下来当你创建新的数据库时,对于SQL Server没有授予这个特权,从错误日志你可以看到,数据和日志文件都被填0初始化了: