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平台設定的原因。