SQL Server 內存相關博文

Don’t confuse error 823 and error 832

本文大意:
     錯誤832:
          A page that should have been constant has changed (expected checksum: 1dcb28a7, actual checksum: 68c626bb, database 13, file 'E:\Program Files\microsoft sql server\MSSQL\data\BlahBlah.mdf', page (1:112644)). This usually indicates a memory failure or other hardware or OS corruption. 
     當一個頁從磁盤讀入,被標記爲乾淨,若是被修改,變成髒頁,檢查checksum,發現checksum再也不可用,832錯誤發生,發生這個錯誤通常出如今:1.內存問題,2.操做系統內存管理器問題,或者流氓程序寫入到sql server。
1.經過微軟產品支持,跟蹤內存
2.經過替換法,替換內存
本文大意:
windows是支持大數據頁的,關於windows大數據頁的支持能夠看Microsoft windows internal,X64支持2MB的大數據頁。
有3個條件決定了是否使用大數據頁:
     1.sql server企業版
     2.內存在8G以上
     3.Lock Page in Memory權限
這個檢查Lock Page in Memory和buffer pool使用AWE API沒有關係,由於Large Page 也是不在work set中,也是不能被page out的。
若是Large Page啓用會在error log中有一下信息:
2009-06-04 12:21:08.16 Server      Large Page Extensions enabled. 
2009-06-04 12:21:08.16 Server      Large Page Granularity: 2097152 
2009-06-04 12:21:08.21 Server      Large Page Allocated: 32MB
可是有人會懷疑,明明沒有開啓TF 834爲何會用large page,由於TF834只限制buffer pool用不用large page。
開啓834以後,buffer pool使用large page,由於large page經過virtualalloc()分配內存,比較慢因此會在開機時一次性分配。
啓動時,分配算法:
1.會根據max server memory 和物理內存的最小值,若沒有設置max server memory那麼會分配全部內存。因此max server memeory的設置很總要
2.當使用large page的時候最讓是sql server專用服務器。
3.若是不能分配,那麼會分配的少一點,仍是不能分配就會報錯,服務沒法啓動。
注意:
     內存size必須是連續的,而且在使用過程當中buffer pool 不會自動增加。
     使用large page致使開機時間變成,由於virtualalloc分配內存比較慢,而且時間不僅僅是分配內存的時間
總結
     1.large page在內存>8gb,並有lock page權限
      2.須要開啓TF834,擦能讓buffer pool使用large page
   2.須要啓動TF834,64操做系統而且已經啓動了large page
     3.large page 並不適用全部場景應該測試後再決定
本文大意:
     做者在64BIT環境下看到一個錯誤,而且被問是否和MemToLeave有關。
     做者解釋了在64bit下並無MemToLeave。
當32bit的年代,虛擬地址空間只有4個g,內核2g,用戶2g,也能夠經過4g選項調整爲內核1g,用戶3g,反正就是不多,設計者會爲buffer pool保留地址,buffer pool有地址了,纔不會影響內存的使用。buffer pool儘可能大的保留地址空間了,但仍是沒有用完地址空間,由於有記下幾個也須要用內存的:
1.線程stack,2.heap,3.SQL Server多頁分配,4.其餘DDL分配。
MemToLeave的意思就是留下來用來作別的事情,好比上面的,當服務啓動的時候sql server 會先保留一部分地址空間,而後buffer pool保留地址空間,保留完以後,memtoleave釋放地址空間。保留的地址的大小以下:線程堆棧大小*線程數+g參數的大小(默認256M)。
當64位來臨,帶來了大量的地址空間,因此沒有必要在再服務啓動時去保留地址空間,直接在須要用的時候分配就行了。
本文大意:
1.sql server 2005啓動的時候發現一致性檢查信息,可是無論數據庫大小,檢查都很快,爲何?
     其實這些並非實際上的檢查,只是把上次最後一次檢查的信息輸出出來。當dbcc checkdb運行完以後會寫入到boot page 上。啓動服務的檢查只是把boot page的信息print出來。
2.如何肯定內存被使用在那個數據庫?
     sql server會佔用大量內存,而且在不必的時候是不會釋放啊內存,除非os有內存壓力。sql server主要的內存都使用在buffer pool中,還有一部分是使用在plan cache中,內存多能夠減小io,能夠減小編譯所佔用的時間。能夠經過sys.dm_os_buffer_descriptors是buffer pool的信息,來肯定是那個數據庫佔用了內存。固然也可使用 dbcc memorystatus 來肯定實例內存的使用。
3.數據庫偶爾會出現SUSPECT和RECOVERY_PENDING的狀況,就會須要經過被備份恢復,會有數據丟失的問題,如何解決?
     這2個狀態都是由故障恢復的時候出現的,當crash 恢復,讀不到日誌的時候會出現RECOVERY_PENDING。當日志可讀,可是日誌能夠訪問,可是沒法完成恢復,一致性不對的時候會出現SUSPECT。有2個緣由會致使恢復沒法完成,1.日誌數據問題,2.數據文件有問題。
還有一個會進入SUSPECT狀態就是,當事務回滾,在回滾時出現錯誤。
可使用備份來恢復數據,若是沒有備份能夠轉入應急模式,來恢復。
4.高安全的數據庫鏡像使用witness是如何識別錯誤的?
     錯誤識別有一下幾種:
     1.sql server實例級crash,每秒ping,能ping通可是發現sql server沒有監聽端口,當即報告
     2.服務器級別crash,每秒ping 不能ping通立刻報告
     3.事務磁盤問題,當日志寫入的隊列過高,20秒後會寫入到error log,40秒後認爲log 磁盤offline,觸發切換
     4.數據庫頁出錯,數據庫會變成suspect狀態,立刻觸發切換
     5.若是文件或者文件組offline,primary正常,當碰到錯誤是切換。
本文大意:
內存浪費是可恥,特別是對於數據庫來講,內存不足有一下幾個特色:
1.物理io變多,無論讀仍是寫
2.Lazy write變多
3.RESOURCE_SEMAPHORE等待變多,由於查詢須要內存
4.大量的plan重編譯,由於沒有地方放plan cache
 
低數據密度:
     使用sys.dm_os_buffer_descriptors能夠看,到底buffer pool 裏面有多少是空的,也就是浪費的。
     低數據密度引發的緣由通常就怎麼幾個:
     1.寬行,那麼就使用小的數據類型
     2.分頁,合理設置填充因子
     3.行刪除,致使內部碎片
     低數據密度也會有一下幾個代價:
     1.io變多,由於空間被浪費了
     2.磁盤空間被浪費
     3.內存被浪費
 
低數據密度解決辦法:
     1.小數據類型
     2.使用順序的key,不要用隨機下降分頁
     3.調整填充因子,填充因子自己就是一種浪費,因此要合理不能太大
     4.重建索引
     5.數據壓縮
做者各處了一些腳本,本身去原文看,我的以爲仍是蠻有用的。
本文大意:
在鏡像服務器出現不能獲取LOCK資源,頗有趣,鏡像是不會動的,爲何會出現這個錯誤?
緣由很簡單,好比一個事務主體回顧的時候,鏡像也回滾,會滾就會產生事務,不信本身試試看。
LOCK結構是須要內存的,儘管很小,可是量大的時候,也是很可怕的,做者就認爲,主體內存和鏡像內存不太一致,致使主體上的lock大量,可是鏡像上沒法達到這個量致使的問題。那麼把2邊的內存搞成同樣,更有甚者,不少回滾事務同時到鏡像,也是會報這個錯誤,那麼就繼續加內存。 做者的意思是加內存。
本文大意:
     做者給出了一個sql用來跟蹤sql server 對虛擬內存的保存和使用。
本文大意:
     VAS也就是虛擬地址,通常處理問題的時候不多去關注虛擬地址,虛擬地址使用VirtualAlloc*/VirtualFree*分配和釋放,能夠保留空間,也能夠分配內存。
     分配內存的方式是:先保留空間而後立刻分配內存,綁定。VAS最小塊爲64KB,並以64KB爲分配單元。
     每一個進程都有VAS,爲了方便使用,在VAS分配以後會分配一個VAS,用來描述VAS。VirtualQuery API和sys.dm_virtual_address_dump都是使用VAD查信息。
     VAS是很重要的資源,因此要跟蹤這些資源,有2個工具:VASUMP,能夠查看VAS利用可是沒辦法查看是哪一個組件分配的。還有一個LEAKDIAG能夠跟蹤到組件級別的信息。
本文大意:
     做者給出了一個跟蹤線程stack的例子,來講明。可使用sys.dm_os_threads,sys.dm_os_load_modules,sys.dm_os_virtual_address_dump鏈接獲取VAS信息
SELECT  *  FROM  sys . dm_os_virtual_address_dump  a
        INNER  JOIN  sys .  dm_os_loaded_modules  b  ON  a . region_allocation_base_address  =  b . base_address
 
SELECT  *  FROM  sys . dm_os_virtual_address_dump  a
        INNER  JOIN  sys .  dm_os_threads  b  ON  a . region_allocation_base_address  =  b  . thread_address
本文大意:
     VAS綁定page是按需的,當page第一次被訪問,綁定發生,一次只能一個頁(綁定和提交有什麼區別?綁定主要作些什麼事情)。若第一次訪問出現硬件頁錯誤,那麼OS嚴重VAD,VAS是否提交,若已經提交,OS會在內存中找一個空的頁,初始化,而且把頁綁定到虛擬地址,並填入數據結構。
     當內存使用緊張,會啓動回收機制,把進程中的要釋放的頁,page 到磁盤上,並修改數據結構,下次訪問的時候就會找到,page 完成後,清零並放到free list中。
     錯誤頁,頁錯誤有3種,最被人說道的是2種1:軟錯誤,2.硬錯誤:
     軟錯誤出如今,第一次訪問的時候,由於mmu中沒有記錄,可是數據頁在內存中存在因此會出現。
     硬錯誤,在內存中不存在在頁面文件中有
     物理頁可以映射到不一樣的VAS,若值映射到一個VAS,咱們就稱私有的,不然就是共享的。使用virtualalloc都不能共享。
     爲了避免讓內存不切換的頁面文件,可使用page lock,page lock會打破系統內內存的平衡,可使用lock page in memory權限打開。
     4G調整和AWE是對虛擬地址的應用,4G調整,讓內核模式只佔用1G的內存空間,其餘3G爲用戶模式地址。
     爲了可以訪問4G以上內存,windows出了一個PAE,物理地址擴展,從32擴展到36能讓windows 訪問64G物理內存,相應出了AWE,經過virtualalloc分配地址並映射到物理內存的方式訪問。AWE的內存os不能page,可是若是濫用,會致使性能問題,只能經過重啓進程來釋放。

本文大意:
     內存壓力分爲2種,1.內部壓力,2外部壓力
     外部內存壓力又分爲,靜態內存壓力:系統運行超出頁面文件,致使系統內存不足,動態內存壓力:os可用內存不足。
     windows會通知進程當前內存是否有壓力,或者你內存太多,應用程序實施的開闢內存或者收縮內存。
     內部內存壓力分爲:1.內存壓力,2.VAS壓力。
     外部內存壓力致使內存收縮就可能英氣內部內存壓力。或者使用內存的限制也可能致使內存壓力。處理方法:收縮stack,pool,把內存返回給內存管理器
     形成VAS壓力的狀況2中:1.VAS碎片致使,沒法開闢聯繫的VAS空間,2.VAS地址空間不夠消耗的。VAS不足會致使,系統變慢,甚至進程終止。處理方法:收縮stack,pool。
     如下幾點要在實現,內存通知的時候注意:
     外部內存壓力出現:內存被page out,內存壓力通知,釋放內存,內存變多,有開闢,又有內存壓力通知以此循環
     當頁面文件變小,沒有通知,而是在下次分配的時候直接報out of memory

本文大意:
內存節點:主要提供本地內存的分配,由一些分配器組成。
內存clerk:clerk有4中類型,generic,cache store,user store,object store,能夠用來跟蹤內存的使用。
內存對象:內存對象的內存分配會被記錄到clerk中。對象分爲3種:1.可變內存對象常規heap,2.自增內存對象,是mark/shrink heap 3.固定長度的內存對象(內存對象內部尚未研究),內存對象和clerk都有頁分配器地址,可使用這個,查看對象對應的clerk。
buffer pool:sp_configure,有2個參數,最大服務內存,最小服務內存,用來控制buffer pool,可是不能控制其餘組件。在服務啓動的時候,sql server 會先保留一部分地址空間,是g參數+最大線程數*512KB(32位,64位爲2M)就是MemtoLeave。而後再爲buffer pool保留地址空間。buffer pool是根據內部內存和外部內存情況按需分配,計算目標內存,根據實際情況計算,並不引發內存壓力,爲了不page,target常常被從新計算。buffer pool分配單元大小是8kb,其餘組件須要內存時能夠用buffer pool做爲底層內存管理。在sql server 啓動的時候buffer pool被設置爲sqlos的單頁分配器。對於大的組件都有本身的clerk,buffer pool也同樣經過VM/AWE/SM分配內存。全部組件從buffer pool分配內存最好,因此小內存分配首選buffer pool,當須要大內存的時候從Mutil Page等分配。
buffer pool和AWE機制:有幾個注意點:1.buffer pool經過clerk來記錄VAS和物理頁的分配,2.buffer pool使用4mb的VAS而不是大的,由於4MB容易對內存壓力作出反應。3.2000中BP是一次性分配的,2005則是按需分配的。AWE不算workset,因此當啓動AWE是,內存分配很難在裏面發現。只有buffer pool可以map,unmap內存,因此其餘組件不能使用AWE。

本文大意:
     內存壓力實際上能夠分爲VAS,物理內存,物理內存壓力多是外部壓力,也多是內部壓力。
     RM運行一些監控的指標,來判斷是否有內存壓力。一旦有問題就會廣播到memory clerk。RM位於cpu節點上,因此可能有多個RM在運行。
     多數內存的消耗,在clerk中都有記錄,並且每一個cpu節點都有一份clerk,RM先計算通知,而後經過list廣播通知。
     有幾個注意點:一、RM有本身的調度器,2.RM運行在非搶佔模式下,3.DAC節點沒有RM
      外部內存壓力,RM,Buffer pool:BP被當作一個單頁分配器,當出現外部內存壓力,RM廣播到clerk,BP從新計算可用內存,而後shrink,一直循環知道壓力消失。可是不低於最小服務內存。
      內部內存壓力,RM,Buffer Pool:當buffer pool出現內存壓力,sqlos經過一些機制打開RM內部內存壓力的標識符,而後通知clerk,buffer pool並不對內部內存壓力做出反應。動態修改最大服務內存,BP中75%的頁被steal也會觸發內部內存壓力
      VAS壓力:當virtual或者shared memory分配4MB的地址空間失敗,或者掃描VAS不存在4MB的連續空間時,通知VAS不足。2000中很難對VAS壓力處理,在2005中會通知全部的clerk全部會有機會去shrink:1.shrink thread,2.卸載CLR,3.network lib收縮buffers。當buffer pool使用AWE時,發現有4MB的地址空間沒有被使用的,也會被釋放。
     經過查看DMV:
SELECT        *
FROM    sys  . dm_os_ring_buffers
WHERE   ring_buffer_type  =  'RING_BUFFER_RESOURCE_MONITOR'     
隨着時間,就很容易看出盡力了哪些內存壓力。

本文大意:
     2000中,cache主要是2種:data page cache:buffer pool,procedure cache:plan cache,plan cache經過buffer pool來完成對cache大小的控制,可是隨着2005,cache變得愈來愈多,因此經過buffer pool控制是不太能夠理解的,因此使用了通用的框架。
     2005中有3總主要的cache 類型:cache store,user store,object store,其中又分爲cache 和pool,其中 cache strore 和user store是cache,object cache 是pool
     cache最主要的特色是:存放各類不一樣的數據,使用cost,結合lru來實現算法。pool:沒有cost,也不須要作lru算法。而且有2個概念:生命週期控制,和可見性控制
     生命週期的算法能夠本身實現,也能夠用框架的,好比cache store 是使用框架的,user store是本身一部分,框架一部分。生命週期經過應用計數管理,
     可見性經過pin count管理
     SQLOS 經過LRU算法實現了可見性和生命週期的控制,模擬LRU算法實現了時鐘策略,外部時鐘指針,和內部時鐘指針。
     外部時鐘指針:經過RM而移動用來控制sql server 總體內存
     內部時鐘指針:用來控制cache 的大小,避免單個cache佔用過大的內存。
     時鐘指針移動並不會影響存儲,而且只有當2個指針都運行過的時候,內存塊纔會被回收。
本文大意:
     64位中仍是可使用AWE的,AWE使用的步驟2步:1.分配內存(PFN),2.映射到VAS中。可是AWE分配的內存釋放1.終止進程,2.程序控制釋放。
     經過頁表項(PTE)來表示用來描述物理內存和VAS的映射,內部物理也經過PFN表示。OS有個庫用來保存PFN,AWE分配後的PFN也保存在這裏,一旦屋裏也綁定到VAS,PFN會指回PTE。AWE分配的內存一旦與VAS綁定就是lock的不會被換出。
     在64位下使用AWE有2個好處:1.不會被換出,對於NUMA有顯示的駐留信息,當被page後很難再回到,原來的處理器,這樣作顯然會增長訪問內存的消耗。2.鎖定是workset和PFN鎖定。這樣可讓應用程序運行的較快,而且擴展性也較好。numa中buffer pool經過queryworkingsetex函數來查詢內存所在的節點信息,由於是lock的因此只須要執行一次便可,提升了性能。惟一要注意的是內存不足時,lock的內存沒辦法被換出,獲取可能內存。
本文大意:
     Q:plan cache太大,會不會形成查找plan的瓶頸,如何控制cache大小?
     A:內部指針用來控制內部單個cache的大小,以避免出現性能問題,當框架預測過程最大cache到達了就會移動內部指針。還有當有一些項進入cache,具體多少項根據最大服務內存來肯定,還有就是機器上的內存狀態。
本文大意:
     NUMA有2中方式,1:純NUMA,2:交錯是NUMA。NUMA是每一個節點都有本身管理的內存,本地訪問代價比遠程訪問代價小。交錯numa是當成SMP訪問,適合對NUMA沒有優化的程序。
     當配置成純NUMA而後重啓,windows就會識別,經過觀察發現大多數內存都是開闢在第一個節點上,開闢的數量和可用內存數量,要啓動的進程有關。這樣的開闢方式會讓內存出現不均衡的情況。
     
     SQL Server Node有本身的內存管理和調度個數,io和其餘組件,node的在線和離線經過affinity設置。在沒有顯示規定指定那個節點是,是經過環形的方式分配。
 
     在SQL變慢,可是plan沒有變化,形成性能降低,每每多是內存的問題引發:
     1.Node 0,系統啓動過程當中都是使用node 0的內存,方法是把node 0 offline
     2.其餘node,查看SFC,其餘進程內存的內存消耗,和SQL Server的內存消耗。方法:在啓動其餘進程前,爲sql server經過設置min,max同樣來保留內存。
     3.錯誤的配置SFC,致使內存的大量消耗。
本文大意:
Memory Broker:用來調整buffer pool,query execution,query優化,cache之間的內存分配,讓內存更有效的使用。根據組件的內存需求調整內存分配,計算最優分配方案,而後廣播到clerk。
SELECT         *
FROM     sys  .  dm_os_ring_buffer
WHERE    ring_buffer_type  =   'RING_BUFFER_MEMORY_BROKER'
NUMA:SQL Server 當本地沒法分配內存的時候會從其餘有內存的節點分配內存。每一個節點內存分配爲max/Nodes 若是設置了affinity那麼就是 max/affinity Nodes
本文大意:
Q1:常常提到保留可是沒有提交是講的是VAS嗎?
A1:是講的是VAS,如當查詢執行須要內存,那麼就會去buffer pool裏面保留內存,這個和VAS的保留和提交時2回事。
 
Q2:爲何不在保留的時候直接提交內存,而是須要先保留而後再提交
A2:先保留的理由有2個1:由於有不少的提交方式,如:AWE,file map等。2:VAS有限,以避免發生沒必要要的爭用。
 
Q3:保留的VAS能收縮或者增加嗎?
A3:一旦被保留就不能grow,收縮,只能一塊兒釋放。
 
Q4:當VAS保留了,可是分配不到內存會發生什麼情侶:
A4:形成這個每每是內存不足引發,會記錄在錯誤日誌上面,ring_buffer也會有一些錯誤,會有OOM通知。
本文大意:
Q1:時鐘指針究竟是幹嗎用的?和lazywrite有關係嗎?
A1:2005把cache分爲2部分,BP和其餘cache,lazywrite仍是會控制數據頁的內存消耗。在2005中引入了通用的cache框架,除了buffer pool以外都會使用這個,這個框架是由RM和一系列store組成,有3中store:cache,user,object。cache,user使用通用的基於cost的LRU算法,object只是一個pool不須要LRU算法和Cost。時鐘指針所過之處,cost減半,當cost變0,就能夠銷燬了,當要重用的時候從新設置cost。指針分爲2中:1.全局(外部),以全局內存作LRU算法。2.本地(內部):以本組件內存作LRU算法。儘管每一個cache都有外部,可是都是同時運行的,就是爲了模擬全局指針。RM經過通知內存壓力來驅動外部指針。內部指針在cache須要被裁剪的時候運行,保證cache的內存佔用的合理大小。
本文大意:
Q1:在sql server2000的MemToLeave的概念是否在64Bit下是否繼續可用?
A1:是的,當組件需求大於8kb的時候仍是會從MemToleave中分配。
 
Q2:大於8KB在MEMToLeave分配,那麼在64位下仍是如此嗎?
A2:仍是同樣的8KB同樣的會從MemToLeave分配,可是有的時候若是數據結構過大的,也會直接從MemToLeave分配
本文大意:
Q: 在個人2005中,開啓了Page Lock碰到了一個問題,我懷疑是內存都沒2005佔用沒有釋放,卻是可用內存不足,致使服務器僵死。如何能和2000同樣當出現內存壓力的時候能夠釋放呢?
A: 在2005中無論是否是Page lock都會對內存壓力作出反應。沒有釋放內存多是沒有cpu時鐘去運行釋放的問題形成。對於page lock的要設置max server memory,有幾個max server memory的建議配置:
< 4GB                   512MB - 1GB
4-32GB                 1GB - 2GB
32GB - 128GB       2GB-4GB
128GB -                4GB-
有記下幾點要注意:
1.當服務器運行在內存的邊界,須要設置max server memroy
2.在高峯期的時候,注意,你的max server memory是否設置在一個合理的值中
3.內存越多max的設置越重要
4.經過測試,或者基線尋址本身的max server memory
5.max worker thread,stacj 在32爲512KB,在64爲2MB,在IA64中爲4mb,因此設置的時候注意是否會引發內存問題
6.max server memory 只對BP起做用,對其餘組件沒有做用
7.對於外部組件,如xps,com的內存分配不受max server memory控制
相關文章
相關標籤/搜索