本文探討 SQL Server 的記憶體使用和分配,強調利用 Windows OS 的資源 API 來管理記憶體。隨著 SQL Server 版本更新,記憶體管理變得更自動化,降低了使用者的學習曲線,並避免了常見的記憶體不足問題。文章還介紹了如何檢測記憶體壓力及建議的配置選項,以提高 SQL Server 的性能。
Rico Chen https://medium.com/ricos-note版權所有,請勿非法複製、散佈
第三章 記憶體壓力
上一章我們已經了解 SQLOS 如何有效率分配 Task,這一章要來說說 SQL
Server 記憶體使用和分配,SQL Server 如安裝在 Windows OS 上,必須透過
Windows OS 公開的各種資源 API 來申請和分配相關資源,而 SQL Server 為了
要有能力同時處理成千上萬的使用者並發請求,也是透過 SQLOS 來使用
Windows OS 所分配的記憶體資源並依據需要自我調整,如此更適合資料庫特
性,也才能更有效率使用記憶體進而達到穩定且高效能。從 SQL Server2005
開始修改記憶體並不需要重新啟動 SQL Server 服務,所以微軟相關記憶體設定
選項少到讓人意外,好比我們無法設定計畫快取區所使用的記憶體大小,完全
由 SQL Server 自我控制,這樣最大好處是降低 SQL Server 學習曲線,讓我們
可以更專注在商業價值上。
每當 SQL Server 發生效能問題時,我一定會分析當前記憶體資源使用情況並確
認是否有瓶頸,但 SQL Server 只要拿到記憶體便不會輕易釋放,這樣的行為導
致某些使用者誤認 SQL Server 有嚴重的記憶體洩漏(Memory leak)Bug,但事
實真的不是這樣,因高記憶體使用和記憶體洩漏真是兩碼子的事,好比 17890
這樣的錯誤是 Windows OS 認為有記憶體壓力,所以會強制要求 SQL Server
釋放記憶體,並非 SQL Server 本身所導致,當發生該情況時,我們可以設定
Windows OS 的鎖定記憶體中分頁權限避免移出分頁(從 SQL Server2012 開始
Rico Chen https://medium.com/ricos-note版權所有,請勿非法複製、散佈
這一章我會說明如何驗證 SQL Server 記憶體壓力,並介紹 SQL Server 發生記
憶體不足有那些特徵,也會說明常見問題及該如何解決,甚至你也可以知道有
那些建議修改的組態選項,因不正確的記憶體設定將造成更多問題(如不熟悉我
建議不如皆使用預設值),由於記憶體分配和使用在 SQL Server 是一個相當複
雜的主題,所以我只針對 SQL Server 可能會遇到的記憶體問題進行介紹。
4.
Rico Chen https://medium.com/ricos-note版權所有,請勿非法複製、散佈
3.1 SQL Server 動態記憶體管理
SQL Server 最主要設計是將硬碟 I/O 最小化,因為硬碟的讀取和寫入,是最
需要用到大量資源的作業之一。 SQL Server 會在記憶體中建立緩衝集區
(Buffer pool),以保存從資料庫讀取的頁面(Page),利用快取可以改善讀取效
能,因為所有資料都從記憶體中讀取,而非從硬碟讀取。SQL Server 也會避免
Buffer pool 過大造成整個系統的記憶體不足,同時也努力最小化資料庫實體檔
案 I/O,預設記憶體管理行為是以不造成系統發生記憶體不足為前提,盡可能
取得所需的記憶體,SQL Server Database Engine 透過一條獨立執行緒定期監
控記憶體使用量,會使用 Microsoft Windows 記憶體通知
API(QueryMemoryResourceNotification)接收來自 OS 訊息,知道目前工作設
定(working-set)可成長多大進而使用更多記憶體(SQL Server 只有當工作負載
需要更多的記憶體時,它才會增加記憶體,否則不會增加其虛擬位址空間(VAS)
的大小),這可避免 OS 記憶體不足而進行分頁,也知道何時該釋放記憶體還給
OS,自我調校這兩個目標並力求平衡。
從 SQL Server2014 In-Memory OLTP 新功能問世,且記憶體價格不像以前高
不可攀,也同時宣告 32 位元(bit)版本正式走入歷史,早期 32bit 作業系統要讓
SQL Server 使用超過 2GB 記憶體(user mode),會需要 AWE(Address
Windowing Extensions) 機制來管理記憶體(需額外設定 3gb 啟動參數),允許