資料庫是個極度吃記憶體的應用程式,因此更需要好好的規劃記憶體的配置與管理,才能避免不必要的麻煩!
前陣子由於筆者所維護的資料庫曾在凌晨時無預警的發生資料庫無法正常運作,最終造成相關應用程式終止運作的慘案。在追查SQL Server 錯誤記錄檔時,發現在異常期間曾頻繁的出現下列訊息。
該錯誤訊息在事件檢視器中也留下相關的事件紀錄(事件識別碼:17890)。
雖然事後已找出其他佔用大量實體記憶體的真凶,不過為防止 Windows 作業系統再將 SQL Server 處理序的緩衝集區(Buffer pool) 移出分頁,根據微軟的建議,在64位元的SQL Server之下,可試著設定「鎖定記憶體分頁 (Lock Pages in Memory)」 來鎖定記憶體。
設定方式就是將SQL Server 服務的啟動帳戶加入鎖定記憶體分頁使用者權限。以下就提供Windows Server 2012 R2的作業環境下,「指派鎖定記憶體分頁的使用者權限」的設定方式。
Step01. [開始]右鍵->選[執行]。於[執行]視窗中輸入gpedit.msc後按[確定],隨即開啟[本機群組原則編輯器]視窗。
Step02.於[本機群組原則編輯器]視窗中,依圖中路徑找到原則:[鎖定記憶體中分頁],按右鍵->選[內容]。
Step03.於[鎖定記憶體中分頁-內容]視窗的 [本機安全性設定] 頁籤中,按下 [新增使用者或群組]。
Step04.加入具有執行 Sqlservr.exe服務權限的啟動帳戶後按[確定]。
Step05.重新啟動 SQL Server 服務。
設定完成後Windows 作業系統將不會再移出SQL Server處理序的緩衝集區(Buffer pool)記憶體,不過Windows 作業系統仍可以逐頁移出 SQL Server 處理序中的 nonbuffer 集區記憶體。
由於資料庫是個極度吃記憶體的應用程式,SQL Server會在記憶體中建立「緩衝集區(Buffer pool)」,用來保存從資料庫所讀取過的資料分頁(data page)。「記憶體組態」中的「最小伺服器記憶體」和「最大伺服器記憶體」就是用來管理「緩衝集區」的上、下限制工具。在這次主機記憶體檢討中,原本SQL Server的「最小伺服器記憶體」和「最大伺服器記憶體」設定皆為「預設值」(同下圖所示)。
在此設定下SQL Server雖可無限制地使用記憶體,缺點是仍會受到作業系統和其他應用程式當下所使用的記憶體數量所限制。因此若該主機為資料庫與其他應用程式共用,基於保護自己也保護他人的原則下(XD),建議還是應該手動調整記憶體上、下限制。
使用「最小伺服器記憶體」可確保 SQL Server 執行個體的緩衝集區有最小記憶體數量可用,且SQL Server啟動時,並不會立即在緩衝集區佔滿「最小伺服器記憶體」,只有在需要時才會逐步向作業系統要求。當到達負載使記憶體使用量達到這個值後,除非降低「最小伺服器記憶體」的值,否則 SQL Server 是不會從配置的緩衝集區釋出記憶體的;而「最大伺服器記憶體」,則應將實體記憶體總數,減去作業系統、其他應用程式或其他SQL Server 執行個體所需要的記憶體,這個差額才是可指派給「最大伺服器記憶體」的參考值。
「記憶體組態」的設定方式為:在SQL Server Management Studio中的[物件總管],選擇[執行個體]按右鍵->選[屬性]。開啟[伺服器屬性]視窗後,選擇[記憶體]作調整。此調整可不用重啟 SQL Server 服務。
值得注意的是,雖然多數資料庫管理者都有設定「記憶體組態」的習慣,「鎖定記憶體分頁」的設定則較少被人注意到。若是有觀察到記憶體在實際釋放與使用率上沒有符合「記憶體組態」預期中的設定時,可試著設定「鎖定記憶體分頁」看看是否有改善哦!
參考資料:
https://support.microsoft.com/zh-tw/kb/918483
https://technet.microsoft.com/zh-tw/library/ms178067(v=sql.105).aspx