開篇小感悟
在實際的場景中會遇到各類奇怪的問題,爲何會感受到奇怪,由於沒有理論支撐的東西才感受到奇怪,SQL Server本身管理內存,咱們能夠干預的方式也不多,因此平常很難遇處處理內存問題的案例。當遇到了原有的知識儲備已經變得模糊,這是已經記不住第幾遍閱讀《SQL 2012實施與管理實戰指南》內存管理章節,也分享給羣友。數據庫
一些內存使用錯誤理解
本文來澄清一些用戶常常對SQL Server內存使用的誤解。對這些知識的理解能夠幫助數據庫管理員理解SQL Server的行爲
1. Windows上還有不少物理內存沒有被使用,就意味着SQL Server不缺內存
這個觀點是很是錯誤的,由於:
(1)SQL Server極可能設置了Max Server Memory,約束了SQL Server繼續申請內存的能力。(
注:實際場景中就遇到過客戶128GB內存的機器SQL Server 的Max Server Memory 被設置成2048MB 致使嚴重的問題)
(2)在32位的機器上 ,因爲虛擬地址空間的限制,SQL Server可能已經沒法繼續申請內存。
例如,在一臺4 GB或更大的32位服務器上,SQL Server最多隻能使用2 GB物理內存。通常Windows會使用500 MB左右的物理內存,這臺機器可能就有1 GB多的空閒物理內存。這部份內存是SQL Server不開AWE就用不到的。 因此,服務器上有不少空閒物理內存,只能說明Windows不缺內存,不能說明SQL Server本身不缺內存。(
這也是爲何建議更換老一代服務器,使用64位的操做系統和SQL Server的緣由)
2. SQL Server進程的Private Bytes(或Working Set)在不停地向上漲,說明SQL Server有內存泄漏的問題
偏偏相反,對於申請內存,SQL Server有嚴格的限制。在32位的服務器上,不論是Buffer Pool仍是MemToLeave,都有一個使用最大上限。當Windows感受到有內存壓力的時候,SQL Server又會主動地釋放內存因此做爲一個進程,SQL Serve發生內存泄漏的機會是很是小的。
之因此會有這樣的疑惑,是由於SQL Server啓動的時候,僅會Commit它啓動所須要的那部份內存。隨着用戶的使用,SQL Server會不斷地申請內存,直到Windows感受到內存壓力,或者SQL到了本身的上限爲止,在這以前,SQL Server的內存使用量的確會不斷地增長。對SQL Server來說,緩存越多的數據,它的性能會越好這種增加是正常的,不用焦慮若是不但願SQL Server使用那麼多內存,只需設置Max Server Memory這個上限便可。
(
注:
實際狀況中不少人提到過,SQL Server居然吃掉了全部服務器的內存,是否是內存泄露了?或問內存是否是這就是我係統的瓶頸呀?)
3. Max Server Memory的值,就是SQL Server內存使用量的最大值。超過這個值就不正常
Max Server Memory這個值應該是Buffer Pool的上限(此點針對SQL Server 2005/2008而言,對於SQL Server 2012內存管理髮生了很是大的變化),而不是SQL Server全部內存使用的上限。因爲SQL Server 內存的使用包括Buffer Pool和MemToLeave,因此SQL Server實際內存使用量必定會比Max Server Memory要大可是在正常狀況下SQL Server MemToLeave的使用會遠小於Buffer Pool的使用,控制好Buffer Pool,就基木控制住了SQL Server的總體內存使用量
(
注:
建議不管內存是否存在壓力都要合理的設置最大內存,PS:我也曾經被使用的內存超過設置的Max Server Memory嚇了一跳)
4. SQL Server的內存使用總量,就是性能監視器裏面的SQL Server:Memory Manager一Total Server Memory的值
性能監視器裏面與SQL Server相關的counter,都是SQL Server本身負責收集的。從SQL Server 2005之後,SQL整合了全部的內存申請,讓它們使用同一的接口。因此SQL Server對本身申請的內存數量,是瞭如指掌的,但問題是,在SQL Server進程裏運行的代碼不都是SQL Server本身的代碼。對第三方的代碼,SQL Server是不知道它們申請了多少內存的。
SQLServer:Memory Manager - Total Server Memory的值,是SQL Server本身的代碼申請的內存空間大小。真正SQL Server進程申請的空間值,會比這個值大一些。(具體大多少和MemToLeave的大小有關係)
若是SQL Server沒有開啓AWE,SQL Server進程申請的邏輯內存數和物理內存數能夠由Process下的Private Bytes和Working Set看出。這兩個值會包含全部的內存支出,包括SQL本身的代碼和第三方的代碼。
若是SQL Server開啓了AWE,問題就比較尷尬了。由於Windows沒有辦法正確判斷出一個使用了AWE 內存的進程,究竟總共用了多少內存。咱們只能藉助SQLServer:Memory Manager一Total Server Memory來判斷SQL Server的Buffer Pool使用量。至於SQL Server本身申請的內存總數(Buffer Pool + MemToLeave ),能夠經過查詢和內存相關的DMV計算出來,但第三方的代碼申請的內存,就很難作精確計算了
5.當系統有內存壓力的時候,SQL Server老是會自動釋放內存
默認狀況下,SQL Server的確會在系統有內存壓力的時候自動釋放內存可是有個例外:SQL Server啓動時會試圖作「Lock Page In Memory」的動做。若是啓動帳號有這個權限,動做就會成功。那麼當同一臺服務器上的其餘應用程序須要內存的時候,SQL Server極可能不會釋放內存。因此在這種狀況下,建議SQL Server設置Max Server Memory上限。
(
注:
Lock Page In Memory不少資料上寫到SQL的內存不會被釋放了,但實際狀況中,當操做系統感受到壓力同樣會把SQL的內存釋放掉,也是錯誤理解6的由來)
6. SQL Server有辦法將本身的內存綁定在物理內存裏
SQL Server的確想經過Lock Page In Memory的方法達到這個目的。可是,做爲一個用戶態爲主的應用程序,它仍是會受限於核心態。若是核心態裏發出內存要求,SQL Server就會被迫把本身的內存釋放出來。
7.增長MemToLeave的大小能夠提升SQL Server的性能
在32位的SQL Server上,默認MemToLeave是256 MB+0.5 MB x ( Max Thread數目)。若是MemToLeave 用完了,SQL Server的一些重要功能就不能進行,甚至新的鏈接都創建不起來因此一些對MemToLeave需求比較大的SQL Server,例如,一些常常運行Linked Server分佈式查詢的SQL Server,或者是一些運行CLR,Extended Stored Procedur的SQL Server,可能不得再也不加一些MemToLeave空間。這可使用SQL Server的
一個啓動參數一g完成。例如,若是想把MemToLeave設成512 MB+0.5 MB x ( Max Thread數目),能夠加啓動參數一g512。
可是須要想清楚的是,SQL Server的虛擬地址空間只有2 GB,給MemToLeave越多,Buffer Pool能拿到的
就越少。Data Cache的內存還能夠從AWE擴展的內存補,Buffer Pool裏的Stolen內存就沒辦法了。因此其實
這是拆東牆補西牆,關鍵要看哪一塊內存對SQL Server的性能和穩定運行最重要。沒必要要多給,這會浪費資源,
影響Buffer Pool裏面的性能。只有肯定了SQL Server的MemToLeave的確不夠,才應該去增大它
8.增長物理內存必定會提升SQL Server的性能
既然SQL Server這麼喜歡內存,那管理員多給服務器配備一些內存,是否是就必定可以提升性能呢?不少時候這個想法是對的,可是並非老是正確。這是由於增長的內存SQL Server不必定用獲得。
(1)首先要檢查是哪一部分的內存有瓶頸,是Database Cache,仍是Stolen,是Buffer Pool,仍是MemToLeave。
(2)要檢查缺的那部份內存是否是已經到了理論上的上限,新加內存SQL Server用不用得上例如,在32位+AWE的服務器上,Buffer Pool裏的Stolen Memory最多也不過1.6 GB。若是是這一部份內存不夠,再加內存也沒有用。只有將系統升級到64位,才能突破這些限制。
(3)加人的內存,通常大部分都會被Buffer Pool使用,這樣SQL Server就會緩存更多的數據頁面和執行計劃,大多數時候這會對性能有幫助。若是Database Pages沒有壓力,SQL Server會緩存太多的動態T-SQL執行計劃,對性能沒什麼好處,反而會增長SQL Server的維護成本。只有在SQL Server的Database Page缺內存的時候,增長內存纔會對性能有明顯幫助。若是數據庫比較小,經常使用數據頁面已經緩存在了內存裏,增長內存對性能不會有太大幫助。
(
注:
內存這個東西對於一些初級DBA分析起來仍是有些難度,而不少狀況下只要看到內存壓力就要添加內存這樣也是不對的,不少時候內存的消耗很本身程序的語句優化程度也有着很是大的關係)
9. Stolen的內存真的是偷來的嗎
不少在描述Stolen的內存塊的時候都說這塊內存是不須要保留(Reserve)而直接提交(Commit )使用的,因此這塊內存叫做Stolen。這麼說錯了嗎?其實,從Windows的層面,對於任何內存的使用,都必須遵循先Reserve再Commit的過程。對於一塊內存,若是不Reserve而直接使用會致使訪問違例(Access Violation)由於SQL Server內部的內存管理機制,全部要使用的內存,Buffer Pool都已經幫咱們保留(Reserve)好了若是SQL所要作的,是用Buffer Pool已經保留(Reserve)好了的那部分地址空間去直接提交(Commit ),並且,這一部份內存又不是用來存放Buffer的,就被稱爲Stolen
--------------博客地址---------------------------------------------------------------------------------------緩存
博客園原文地址: http://www.cnblogs.com/double-K/服務器
歡迎轉載,請保留出處。分佈式
-----------------------------------------------------------------------------------------------------性能
總結 : 本文介紹了一些常見的內存方面的誤區,都是文字描述,可能不少人沒法真正的理解,但當遇到過這樣的場景或奇怪的問題發生時,回頭看看也會加深一下感覺的!
優化
PS:我也是當遇到真正場景時才能明白,理論知識也是須要不斷熟悉、不斷理解的。spa
----------------------------------------------------------------------------------------------------操作系統
注:此文章爲原創,歡迎轉載,請在文章頁面明顯位置給出此文連接!
若您以爲這篇文章還不錯請點擊下右下角的推薦,很是感謝!blog