使用即時文件初始化提高SQL Server性能


今天我想談下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步需要重建文件。

  1. SQL Server第1步創建10GB“空”的數據庫,在NTF文件系統里數據文件會被填0初始化。
  2. 最后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是否帶這個權限在運行,你可以啟用30043605跟蹤標記。用這些啟用的跟蹤標記,SQL Server在錯誤日志會報告那個文件被填0初始化。接下來當你創建新的數據庫時,對於SQL Server沒有授予這個特權,從錯誤日志你可以看到,數據日志文件都被填0初始化了:

如果SQL Server有執行卷維護任務(Performance Volume Maintenance Task)特權,從錯誤日志你可以看到,只有日志文件被填0初始化:

 

Windows內核

在SQL Server運行下服務帳號,你對它授予了執行卷維護任務(Performance Volume Maintenance Task)特權,在Windows操作系統內部會發生什么呢?啟用這個特權后(它內部是通過WIN32 API調用所謂的SE_MANAGE_VOLUME_NAME函數),SQL Server可以調用SetFileValidData的WIN32 API函數。從在線文檔里可以看到,調用那個函數的進程,有SE_MANAGE_VOLUME_NAME權限。當那個函數被SQL Server調用時,函數本身會設置文件所謂的High Watermark——在其NTFS簇里,文件直接擴展而不重寫原始內容!正如在線文檔所述:

 

“The SetFileValidData function allows you to avoid filling data with zeros when writing nonsequentially to a file. The function makes the data in the file valid without writing to the file. As a result, although some performance gain may be realized, existing data on disk from previously existing files can inadvertently become available to unintended readers.”

 

 

“If SetFileValidData is used on a file, the potential performance gain is obtained by not filling the allocated clusters for the file with zeros. Therefore, reading from the file will return whatever the allocated clusters contain, potentially content from other users. This is not necessarily a security issue at this point, because the caller needs to have SE_MANAGE_VOLUME_NAME privilege for SetFileValidData to succeed, and all data on disk can be read by such users.”

 

我已經說過,對於你的SQL Server實例,你是否啟用這個權限主要是關系到安全的。

小結

對於你的SQL Server實例,你是否應該啟用即時文件初始化?這個依具體情況而定……當你是SQL Server和系統管理員時,授予這個權限是個好主意,因為作為系統管理員,你總是可以訪問文件系統的。但當你有專屬的系統管理員和SQL Server管理員時,這就不可能授予了,因為系統管理員並不信任你,對於你的SQL Server實例你不會獲得這個權限。那樣的話SQL Server總會填0初始化數據和日志文件……

感謝關注!

參考文章:

https://www.sqlpassion.at/archive/2014/02/18/improving-sql-server-performance-by-using-instant-file-initialization/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM