探索系列——神人steve adams之著oracle8i interal service(十八)

wisdomone1發表於2010-05-10
記憶體
       

      好多效能問題皆與記憶體分配有關.oracle動態管理它的記憶體元件使得問題更為複雜多變.為了有效調節oracle,應該理解
記憶體的用途(用於什麼)及如何管理這些記憶體.


sga
      sga連同基本的後臺程式,就是一個oracle例項.從全域性層次上來講,它包含全域性變數和資料結構,它從某種層次來講,就是一個系統局域,包含可以被整個oracle例項訪問的資料結構,而不僅僅是針對某個特定的程式.


sga areas
      sga包括4或5個主要的區域
         the fixed area 固定區域
         the variable area 可變區域或動態區域
         the database block buffers
         the log buffer
         the instance lock database(for parallel server instances)
如果從記憶體佔用尺寸來講,固定區域與log buffer就是微不足道或可以忽略掉



the fixed area
       包括數以千計的原子型變數,微小或細小的資料結構如:latches和指向sga其它區域的指標變數.這些變數的內容可以查詢x$kxmfsv,得到它們的資料型別,大小,記憶體地址.這些變數含義很模糊,很少有人知道它們.
但是oracle資深員工透過聯結x$ksmfsv和x$ksmmem得到高階診斷資訊,可以監控這些變數的值,用來調查它們指向的資料結構內容.x$ksmmem對於sga每個記憶體地址有一條記錄,同時它的很個非鍵列顯示記憶體地址的內容.

固定區域的每個元件大小是固定的.也就是講,它們不依賴於任何初始化引數的設定,或者其它的一些配置.所以對於每個變數的固定sga的偏移量是固定的,從而它的總體的大小也是固定的.


the variable area
       由large pool和共享池組成.大池所有記憶體是動態分配,然而共享池包含動態分配的記憶體和固定的記憶體.shared_pool_size實際上指定用於動態分配的共享池的近似大小,而非共享池本身的大小.共享池的固定記憶體部分包含,
一系列的資料結構如:buffer headers,程式,會話,事務佇列,入隊資源和鎖,在錢rollback segment佇列,以及記錄統計的各種各樣的佇列.
       大多數佇列的大小與一個或多個初始化引數有關.這些初始化引數改變必須要重啟例項方可,因此固定記憶體佇列的大小在每個例項的生命週期內是固定的.比如,process佇列大小是由processes引數配置.如果這個佇列的所有slots正在使用,然後嘗試
在例項中分配更多的程式會失敗,因為這個佇列不能動態改變大小.
       對於一些固定記憶體的佇列,這是(或它們是)一些x$表,以一行顯示或展示每個佇列element,它的某些結構成員以列方式顯示.這些x$表有時叫固定表.因此這兒有它們對應的v$檢視,不過它們只顯示x$表中最有用的一些列,但僅僅顯示代表目前在用的佇列slots的記錄.比如,
v$process檢視是以x$ksupr固定表為基礎,而x$ksupr以記憶體中的process array程式佇列為基礎.v$process不包含x$ksupr所有的行與列,x$ksupr也不顯示sga程式結構所有的成員.

       the variable area的大小等於large_pool_size加上shared_pool_size,加上固定記憶體佇列的大小.固定記憶體佇列的大小,從理論上講,根據這些初始化引數計算出來.但是,你應該知道根據這些引數計算佇列大小的公式,每種佇列element的大小,佇列頭的大小.同時在不同版本間有所變化的,而且與os有關.
你也要認識到每一個固定記憶體佇列是在一個記憶體頁範圍上進行分配的,為了最佳化記憶體定位(地址定位)定址,因此一些空間沒有使用.幸運的是,基本上沒有必要去精確計算固定記憶體的大小.如果你真的想得到這些資訊,你用一個dummy sid啟動一個測試例項,可以度量固定記憶體大小,不用載入一個資料庫.




the database block buffers
       在sga儲存資料庫的資料塊的sga buffers 複製區域.db_block_buffers表示緩衝區的數目,每個緩衝區大小為db_block_size.這個區域僅包含緩衝區數,沒有它們的控制結構.對於每個緩衝區,在sga的可變區域有一個對應的buffer header.同樣,工作集頭,hash chain頭,它們的latches駐存於sga的可變區域.因而,
你會發現sga的可變區域,對於sga database block buffers緩衝區數每四個緩衝區,將會以1k大小而改變.







the log buffer
       它的值由log_buffer控制.但是,如果嘗試給它一個值小於它的最小值(所支援平臺的4倍的資料庫塊大小),它將會靜然加大大小.如果是在支援記憶體保護的os下,the log buffer會由兩個保護頁所包括(更為準確的是,記憶體保護單元),為了防止讓錯誤oracle程式破壞log buffer.但是,log buffer相對於可變區域與database block buffers,是可以忽略的.
the log buffer從內部分為好多資料塊的.每個log buffer block,在sga的可變區域皆有一個8 byte的頭.



the instance lock database
       在並行伺服器配置中,例項鎖用於在多個例項間序列化訪問共享的資源.這個區域維護這個例項感興趣的相關資源,以及需要這些資源的程式及例項,目前正在持有的鎖或者這些程式和例項發起的請求.這三個佇列的大小由lm_ress,lm_procs,lm_locks來控制。例項鎖資料庫也包含訊息緩衝區和其它結構.甚至在單例項資料庫中也需要這種記憶體區域,但是這個大小可以忽略.
當在例項啟動時報告這個組成和sga大小,這個區域目前不包含在oracle中;但是,透過在svrmgrl中用oradebug ipc檢視dumps會發現它的身影.



overhead
       sga最後一個細小或微小區域是共享記憶體成本本身.這個區域包含正在使用的共享記憶體segment的資訊,以及它們包含的sga區域及子區域.





shared memory
        在大多os中,sga是駐存於共享記憶體上.為了理解共享記憶體segments,你需要了解記憶體segment,也叫虛擬記憶體.

virtual memory addressing 虛擬記憶體定址
        今天虛擬記憶體定位技術很為流行,導致它的替代物直接記憶體定址基本僅僅是一個記憶體.如果你曾經在z80或8086 cpus
上進行過程式設計,你應該還記得直接記憶體定址.你必須知道可用的記憶體地址的精確位置,因此不用引用不存在的記憶體否則會破壞bios.
如果你要寫一個大型的程式,大於可用的記憶體或地址空間,你必須把它分割為不同的節,便於載入或者切換到記憶體中(根據需要).
事實上,初期oracle二階段架構設計就是源於這個問題.
        虛擬記憶體定址在程式程式碼與實體記憶體間引入一個抽象層.在每個指令執行前,所有引用的記憶體會動態從虛擬記憶體地址翻譯為或轉變為
實體記憶體地址.os維護資料結構,叫作頁表page tables,為了支援虛擬到實體記憶體地址轉變.為了最佳化地址轉變,在每個cpu上快取最近使用的
頁表條目,這個快取通常叫作tlb(translation lookaside buffer).為了更進一步最佳化地址轉化,tlb查詢會在硬體中實施.一個tlb miss必須
透過在主記憶體引用頁表解決或處理.這個操作有一些情況下也是透過硬體來實施.如果硬體地址轉變失敗,cpu切換為一個特定的執行上下文,用於
確保為這個虛擬頁分配一個實體記憶體頁,如果有必要,從磁碟進行重新整理.這個頁表條目也被複製到tlb中.這種硬體地址轉變失敗叫作page faults
頁故障--否則就是一個軟或次級頁故障.當處理了這個次級頁故障後,cpu切換回使用者模式然後重新開始當前的指令.但是,當一個主要的頁故障處理完
後,用cpu time服務其它的程式.
        虛擬記憶體定址使得程式執行,不用全部的程式碼或資料都駐在實體記憶體中.這意味著相對不太活躍的虛擬頁可以暫時從實體記憶體中移走如有必要.
如果這些頁被修改後,它們必須儲存在磁碟中一個臨時的儲存區域,叫作一個分頁檔案paging file或交換空間swap space.
把一個或一系列的不活躍的記憶體頁寫到磁碟的操作叫作一個頁出page out,如果當引用一些頁從而這些頁再次被讀入記憶體的對應操作叫作頁入page in.
paging分頁是虛擬記憶體管理的一個方面,允許一個大型程式可以執行。典型情況在任何情況下,每個時刻只有一部分虛擬記憶體頁處於活躍狀態.一個程式
正在使用的一系列的記憶體頁叫作它的工作集working set.
        虛擬記憶體定址也讓程式可以在實體記憶體的基本上所有位置上執行.這意味著同時會有許多程式和它們的資料存在,在它們之間可以快速切換.cpu time
不會浪費,當一個程式實行磁碟i/o或者等待使用者輸入,或處理一個頁故障時.




memory access
        大量繁重的換頁活動會對效能產生極大的影響,這個會在後面討論.但是首先,一定要認識到地址轉換本身和記憶體訪問,除了分頁paging, 也會極大影響效能.
主記憶體訪問在cpu週期內是個很expensive的操作.記憶體操作比cpu操作處理在硬體時鐘速度方面要慢好多,在每個記憶體訪問之後,同時在每個記憶體bank可以服務相同cpu(或不同cpu)發起
的另一個記憶體訪問,這兒會有一個必需的恢復時間部分.這就是為何現在的計算機制造商花費大把心思在cpu快取技術上了.
不僅頁表條目快取中tlb上,部分使用者記憶體(也叫快取記錄或快取行cache lines)也會快取在一個通用或普通的快取中.採用這種複雜多變的機制維護主記憶體和cpu快取(也叫快取coherency 機制)
的一致性.快取行會盡可能儲存,為了最大限度cache hits,程式程式碼與資料因為它們不同的位置特徵,從而有顯著的區別.從os層次來講,排程法則或演算法會有偏向性地為要排程的程式分配
這些程式經常根據最常使用的cpu上分配一個時間片.這樣設計為了減少硬體地址轉變失敗的可能性和cpu cache misses,因而減少了主記憶體訪問.

       





process memory segments
      虛擬記憶體定址一個好處就是,程式可以使用一個更大的虛擬記憶體地址空間而不管實體記憶體是否可用.這使得程式記憶體從邏輯上根據不同的用途分割為不同的segments.這些segments可能對映到不連續的虛擬記憶體地址,這樣就允許或考慮到以後的segment增長.oracle使用下面的segment types,通常
程式分為如下幾種型別:
    
   program text
       這個文字segment包括程式本身的可執行機器程式碼,不含動態連結共享庫.文字segments正常情況標記為只讀,以便它們在執行相同程式的多個程式間共享.比如,所有的oracle程式執行相同的oracle binary,雖然是以不同的方式personalities.不管一個例項中執行多少個程式,不管在同一個伺服器上
執行多少個例項,在實體記憶體中只有僅僅一個程式文字的複製
  
   intialized global data
       包含編譯器進行初始化時包含的一些全域性資料結構,比如用於trace輸出的文字字串.初始化資料從理論上可以修改,因此在執行相同程式的多個程式間不能共享.oracle很少使用這個segment
   uninitialized global data
       通常情況下叫作bss(根據符號啟動的塊)segment.包含靜態分配的全域性資料結構,這些結構是在執行時由程式本身進行初始化.oracle是最小限度使用這些bss segment.

   data heap
       程式在執行過程中透過malloc()及sbrk()系統呼叫,為了給程式動態分配記憶體.oracle作用它用於pga(process glabal area)
   execution stack
       只要一個函式被呼叫時,它的引數及返回上下文return context被推入pushed into執行堆疊中.返回上下文字質上就是一系列的cpu註冊值,用於描述函式呼叫哪個時間點上程式的準確狀態.當函式呼叫結束時,堆疊被彈出而且上下文傳會繼續以便繼續從這個函式呼叫開始執行指令.這個堆疊也會在本地
         儲存一份程式碼塊.堆疊大小和函式呼叫巢狀深度有關,或者遞迴呼叫,以及引數的記憶體需要和本地變數有關.oracle堆疊空間條件是適度的,根據它的複雜度.
   shared libraries
       它是與位置有關的執行程式碼(可能是多個程式執行時需要它)的集合--特別是,系統呼叫函式的集合.通常情況下,標記為只讀,在所有相互依賴的程式間共享,包含oracle程式.在呼叫一個共享庫之前,程式必須首先開啟這個共享庫檔案,透過mmap()系統呼叫把它是對映到它的地址空間.
       替代共享庫的方法就是在程式文字segment中包含必需的系統呼叫函式.它適用於某些不支援共享庫的os,或者它的實施或完成是有問題的.在大多os中,oracle使用系統呼叫函式的共享庫,而不僅僅用於oracle伺服器程式碼本身.但是,java  class庫編譯然後動態連結為共享庫.
 

   shared memory segments
       共享記憶體允許相關或有關係的程式在記憶體中協同讀寫公用的資料結構.每個需要定位address一個共享記憶體segment的程式,必須首先把這個segment attach附加到它的虛擬地址空間.正常情況是以shmat()系統呼叫來完成.oracle的sga使用共享記憶體segment



在一個程式中虛擬地址空間,這些segment的位置是和不同的os有關.
 

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/9240380/viewspace-662311/,如需轉載,請註明出處,否則將追究法律責任。

相關文章