天天看點

SHMMAX參數與SGA空間配置設定

Oracle Instance執行個體就是Oracle資料庫伺服器上一塊可共享記憶體和一系列的背景程序。在Windows環境和Unix/Linux環境中,實作Oracle執行個體的方式存在很大差異。Windows環境由于自身的特點,Oracle執行個體中的共享記憶體和多程序模型被實作為單程序多線程模型。此時的共享記憶體SGA被實作為程序OracleService.exe的專享區域。

而在Unix/Linux下,Oracle執行個體是被實作為多程序模型的,多程序之間通過信号量(semaphore)和共享記憶體(shared memory)進行通信。在這個過程中,作業系統層面要進行更多的共享記憶體和信号量管理工作。本篇,我們就研究一下作業系統的shmmax參數含義和與SGA配置設定的關系。

1、Oracle執行個體啟動和共享記憶體

回顧兩個問題:

ü       在Oracle Startup的時候,要經曆三個階段:unmount、mount和open。在unmount階段,Oracle會進行執行個體的建立和整理工作。具體來說包括:參數檔案init.ora讀取、backgroup process建立和共享記憶體SGA配置設定;

ü       我們在安裝Unix/Linux版本的Oracle時,是需要手工配置一些參數内容。其中就有shmmax參數的配置。該參數的作用就是定義Unix/Linux環境一次可以配置設定的最大共享段segment的大小;

配置shmmax參數就在/etc/sysctl.conf中。

[[email protected] ~]# cat /etc/sysctl.conf

# Kernel sysctl configuration file for Oracle Linux

kernel.sem = 250 32000 100 142

kernel.shmmni = 4096

kernel.shmall = 1073741824

kernel.shmmax = 4294967295

net.core.rmem_default = 262144

(篇幅原因,有省略……)

共享記憶體資訊為:

[[email protected] ~]# ipcs

------ Shared Memory Segments --------

key       shmid     owner     perms     bytes     nattch    status    

0x1e853bdc 32768     grid      660       4096      0                     

0x01606d30 98305     oracle    640       4096      0                     

------ Semaphore Arrays --------

key       semid     owner     perms     nsems   

0x00000000 0         root      600       1       

0x00000000 32769     root      600       1       

0xa83075d0 163842    grid      660       104     

0xc05587f0 294915    oracle    640       154     

------ Message Queues --------

key       msqid     owner     perms     used-bytes  messages

2、SGA空間配置設定方式

SGA的大小是Oracle執行個體相關的一個重要方面。在Oracle10g之前,SGA總大小是根據DBA進行手工調整配置。但是進入10g之後,可以使用sga_target參數進行統一劃定,其中各個部分組成由Oracle自動根據負載進行動态調整。在11g之後,使用memory_target參數,更進一步的将整個Oracle伺服器所有使用空間進行自動化調整。

在執行個體啟動的時候,Oracle會從參數檔案parameter file中讀取需要建立的SGA大小,之後就會向作業系統申請相應的共享空間。在這個過程中,需要結合shmmax參數與SGA參數進行比對。

單對于SGA而言,是劃分為四個組成部分的:

ü       Fixed Portion:是一個固定的配置設定常量;

ü       Variable Portion:可變部分,大部分的可變部分都是由shared_pool的大小來确定的;

ü       Redo block buffer:是Oracle SGA的redo buffer pool的空間;

ü       Data block buffer:是SGA的buffer cache的空間使用;

SQL> select * from v$sga;

NAME                     VALUE

-------------------- ----------

Fixed Size             1250428

Variable Size        222301060

Database Buffers     381681664

Redo Buffers           7135232

3、配置設定SGA的三種方法

簡單的說,在SGA分布在實體記憶體的方式上,存在三種模型:單段(one-segment)、連續多段(contiguous multi-segment)和非連續多段(non-contiguous multi-segment)。

在Oracle啟動執行個體,進行共享SGA配置設定的時候,會依次嘗試着三種方法。在每個方法嘗試中,配置設定成功或者最後抛出相關ORA異常。如果出現異常抛出,Oracle會以異常處理的方式,清理錯誤資訊,嘗試下一種配置設定模型。最後,整個SGA會存放在shared memory中,共享記憶體的各個片段累積和就是sgasize的大小。

ü       One-segment單段

單段one-segment是sga配置設定最簡單也是最先嘗試的一種模型。該模型下,SGA會配置設定在一個共享記憶體區域裡。采用這種模型時,Oracle會向記憶體申請配置設定一塊與SGA期望大小相同的共享記憶體空間。

在作業系統層面,oracle相當于調用shmget核心函數進行配置設定。但是該操作所能配置設定的最大共享記憶體大小受到參數shmmax的限制。如果申請的共享記憶體SGASIZE大小小于或者等于shmmax的大小,這樣通常是可以申請到共享記憶體segment的。

但是,如果設定的SGA大小超過了shmmax空間,shmget函數操作就會傳回一個錯誤資訊。這樣,SGA就需要放在多個共享段multi-shared segment中了。

注意兩個細節:如果shmget()函數在配置設定過程中,遇到非空間不夠問題,會抛出錯誤ORA_7306。在配置設定空間之後,會将共享記憶體的配置設定資訊計入到ksms.o檔案中。這個過程被稱為attach過程,如果這個過程出錯,系統報錯ORA_7307。

ü       Multi-Segment Contiguously連續多段配置設定

當沒有成功的将SGA放置在一個共享記憶體段時,Oracle會開始嘗試放置在多個段中。這個方法有兩種類型:一個是連續的配置設定多段,另一個是非連續的多段配置設定。首先嘗試的是連續contiguously方式的配置設定。

此時,Oracle需要直接通路擷取shmmax參數,進而了解到底需要配置設定多少個共享段。大部分情況下,需要多段配置設定的場景都是shmmax<sgasize。

在連續共享段的配置設定方式下,Oracle會配置設定SGASIZE/SHMMAX(向下進位)個分區給SGA。由于空間是連續的,是以容納SGA的時候也是連續存放。

對多個配置設定下去的共享記憶體,同樣存在allocate和attach的過程。在attach到ksms.o檔案的時候,隻會将配置設定的第一個共享段首位址放置。其他的共享段都是通過上一個的位址加上空間大小,進而實作連續配置設定的效果。

注意:如果這個配置設定的共享大小個數超過了SS_SEG_MAX規定的大小數量,那麼Oracle會報錯ORA_7329。

比如:SGASIZE的大小是5G,而shmmax參數為2G。此時系統若有條件進行連續共享段配置設定,會配置設定出:2G、2G、1G三個共享段連續排列。

如果連續多共享段操作配置設定失敗,Oracle内部會傳回錯誤ORA_7336。那麼就意味着第二種配置設定模型失敗。要根據傳回錯誤的具體值進行判定。

如果在allocate過程中出現錯誤,而且傳回資訊為EINVAL,則直接轉入到第三種配置設定SGA模型中。否則,Oracle會持續報錯ORA_7337。

ü       Multi-Segment Non-Contiguously非連續多段配置設定

第三種配置設定模型是三種模型中最複雜的一個。首先,Oracle也是會去擷取shmmax參數的取值,之後進行一系列複雜的評估過程。按照如下步驟進行:

1、Oracle檢查是否有一個shared memory segment可以将SGA的fix portion和variable portion兩塊存放在一起。如果可以,将兩個部分放置在一個共享段中;

2、如果步驟一的檢查失敗,那麼轉而嘗試是否可能将fix portion和variable portion分别放置在兩塊共享記憶體上;

3、在這個過程中,如果fix portion要大于shmmax參數,也就意味着不存在單獨可以防止fix portion的空間,那麼系統報錯ORA_7330。如果variable portion要大于shmmax參數,系統報錯ORA_7331;

4、Oracle計算容納進一個shared memory segment的redo block的個數。如果shmmax的大小小于一個redo block的大小,系統報錯ORA_7332;

5、同理,Oracle計算容納進一個shared memory segment的data buffer block的個數。如果shmax的大小小于一個data buffer block,Oracle抛出錯誤ORA_7333;

6、通過步驟4、5的計算,Oracle擷取到容納redo buffer和data block buffer的共享段的個數。注意,redo buffer和data block buffer的計量方式是通過blocks進行的。是以,使用buffers/(buffers per segment)可以近似擷取到容納的segments個數;

7、SGA四部分配置設定到需要的segment數量之後,總和就是總的共享segment個數。如果這個綜合超過了ss_seg_max參數,報錯ORA_7334;

經過一系列的計算确定,Oracle最後還是要進行空間的allocate和attach過程。在ksms.o中,會記錄上對應的所有segment的頭位址和大小資訊。

在算法中,如果Oracle接收到作業系統級别的錯誤,首先會抛出ORA_7336錯誤,之後檢查傳回錯誤參數。如果是EINVAL,就抛出錯誤ORA_7310。否則是ORA_7337。

4、結論

經過三種算法的計算配置設定,Oracle擷取到了和SGASIZE相同的共享記憶體。之後的過程就是進行信号量semaphore的配置設定。

綜合上面的闡述,我們也就了解了shmmax參數在Unix/Linux平台設定的原因。