☞ 實例是一組後臺進程和共享內存java
☞ 數據庫是磁盤上存儲的數據集合算法
☞ 實例「一輩子」只能裝載並打開一個數據庫數據庫
☞ 數據庫能夠由一個或多個實例(RAC)裝載和打開緩存
[oracle@drz ~]$ ipcs -a服務器
##顯示進程間的通訊設備,如共享內存、信號量等。網絡
ORACLE_SID是Oracle的站點標識符,它是訪問實例的鍵,設置命令以下:數據結構
[oracle@drz ~]$ export ORACLE_SID=drz多線程
Oracle實例和數據庫oracle
Oracle中內存部分也稱爲系統全局區(SGA),它的主要做用是:app
①維護全部進程須要訪問的多種內部數據結構;
②緩存磁盤上的數據,另外重作數據寫至磁盤以前先在這裏緩存;
③保存以解析的SQL執行計劃,等等。
☞ 專用服務器
常見的專用服務器配置
當有客戶鏈接時,Oracle會爲客戶端建立一個新的進程,一般稱爲專用服務器配置,這個服務器進程會在客戶端會話生存期中專門爲客戶端服務。會話與專用服務器之間是一對一映射關係。按照定義,專用服務器不是實例的一部分。客戶進程會經過某種網絡通道與這個專用服務器直接通訊,並由這個服務器進程接收和執行SQL,必要的時候它還會讀取數據文件,並在數據庫的緩存中查找客戶想要的數據。專用服務器進程的主要目標就是對客戶提交的SQL調用做出響應。
☞ 共享服務器
當客戶以共享服務器鏈接時,Oracle不會對每一個客戶的鏈接建立另外的線程或新的Unix進程。在Oracle7x和8x中,共享服務器叫作多線程服務器(MIS),如今已經棄用此名稱。共享服務器實際上就是一種鏈接池機制。利用共享服務器,Oracle只需創建不多的一部分進程/線程,這些進程/線程將由全部會話共享。
共享服務器鏈接和專用服務器鏈接之間的最大區別是,與數據庫鏈接的客戶進程不會與共享服務器直接通訊,由於這個服務器進程是共享的。爲了共享這些進程,Oracle使用了一個或一組稱爲調度程序(dispatcher,也稱爲分派程序)的進程。客戶進程經過網絡與一個調度程序進程通訊,這個調度程序將客戶的請求放在SGA中的請求隊列中。第一個空閒的共享服務器會獲得這個請求,並進行處理。完成這個命令後,共享服務器會把響應放在原調度程序的響應隊列中。調度程序進程一直在監聽這個隊列,發現這個結果後,就會把結果傳給客戶。整個流程以下圖:
共享服務器請求的流程步驟
上圖中,客戶鏈接向調度程序發送一個請求。調度程序首先將這個請求放在SGA的請求隊列①中。第一個空閒的共享服務器從請求隊列中取出這個請求②並處理。共享服務器處理結束後再把響應放在相應隊列③中,接下來調度程序拿到這個響應④,傳回給客戶。
當咱們使用TCP/IP鏈接時,會鏈接一個TNS服務名。TNS就是透明網絡底層(Transparent Network Substrate),它是Oracle中處理客戶遠程鏈接的「基礎」軟件。TNS鏈接串告訴Oracle軟件如何與遠程數據庫鏈接。通常在客戶端都有一個tnsnames.ora文件,一般存放在$ORACLE_HOME/network/admin目錄下。
當客戶遠程鏈接數據庫時,服務器端會有一個監聽器在tns指明的端口處監聽鏈接請求,當監聽器收到入站鏈接請求後,它會使用本身的配置文件檢查這個請求,符合要求會被容許鏈接,不符合要求會被拒絕鏈接。
Unix上監聽器進程和專用服務器鏈接
當咱們發起專用服務器鏈接,監聽器進程會爲咱們建立一個專用服務器。在Unix上,這是經過fork()和exec()系統調用作到的(在Unix中,要在初始化以後建立新進程,惟一的辦法就是經過fork())。這個新的專用服務器進程繼承了監聽器創建的鏈接,如今就與數據庫物理的鏈接上了。在Windows上,監聽進程請求數據庫進程爲鏈接建立一個新線程。一旦建立了這個線程,客戶就會「重定向」到該線程,而後就能創建物理鏈接了。
監聽器進程知道實例中運行了哪些調度程序。接收到鏈接請求後,監聽器會從可用的調度程序池中選擇一個調度程序進程。監聽器會向客戶返回鏈接信息,其中說明了客戶如何與調度程序進程鏈接,還可能把鏈接「轉發」給調度程序進程(這由不一樣的操做系統和數據庫版本決定)。監聽器返回鏈接信息後,它的工做就結束了。而後客戶直接與調度程序鏈接。
監聽器與共享服務器鏈接
Oracle主要由三個內存結構:
系統全局區(System Global Area,SGA):這是一個很大的共享內存區域,幾乎全部的Oracle進程都會訪問這個區域。
進程全局區(Process Global Area,PGA):這是一個進程或者線程專用的內存,其餘進程或者線程不能訪問。
用戶全局區(User Global Area,UGA):這個內存區與特定的會話相關聯。當使用共享服務器時,UGA在SGA中分配;若是使用專用服務器,UGA在PGA中分配。
查詢v$SGASTAT視圖能夠獲得SGA內部內存分佈:
select pool,name,bytes from v$sgastat order by pool,name;
SGA主要包括如下池:
①Java池(Java pool):Java池是爲數據庫中運行的JVM分配的一段固定大小的內存。在Oracle Database 10g中,Java池能夠在數據庫啓動並運行時在線調整大小。
②大池(Large pool):共享服務器鏈接使用大池做爲會話內存,並行執行特性使用大池做爲消息緩衝區,另外RMAN備份也可使用大池做爲磁盤I/O緩衝區。大池能夠在線調整大小。
③流池(Stream pool):這是Oracle流(Stream)專用的一個內存池,Oracle流是數據庫中的一個數據共享工具。這個工具是Oracle Database 10g中新增的,能夠在線調整大小。若是未配置流池,可是使用了流功能,Oracle會使用共享池中至多10%的空間做爲流內存。
④共享池(Share pool):共享池包含共享遊標(cursor)、存儲過程、狀態對象、字典緩存和諸如此類的大量其餘數據。在Oracle Database 10g和9i中,共享池均可以在線調整大小。
⑤「空」池(Null pool):這個池其實沒有名字。這是塊緩衝區(緩存的數據庫塊)、重作日誌緩衝區和「固定SGA」區專用的內存。
典型的SGA
在9i中,必須手動設置SGA的大小,10g中能夠自動SGA內存管理,11g中能夠自動內存管理。當採用自動內存管理時,只需設置MEMORY_TARGET值,數據庫實例會自動的把SGA和PGA分配爲最佳大小。
不管是自動內存管理仍是手動內存管理,各個池的內存以顆粒(granule,也稱爲區紐)爲單位進行分配。一個顆粒是大小爲4M、8M或16M的內存區。顆粒是最小的分配單位,因此想要一個5M的Java池,並且顆粒大小是4M,Oracle實際上會爲這個Java池分配8M.顆粒的大小由SGA的大小肯定,能夠查詢v$sga_dynamic_components視圖。
select component,granule_size from v$sga_dynamic_components;
固定SGA(fixed SGA)是SGA的一個組件,其大小因平臺和版本而異。安裝時,固定SGA會「編譯到」Oracle二進制可執行文件自己中。在SGA中,有一組指向SGA中其餘組件的變量,還有一些變量中包含了各個參數的值。固定SGA一般很小,大小不受控制。能夠把這個區理解成SGA中的自啓區,Oracle在內部要使用這個區來找到SGA的其餘區。
若是數據須要寫到在線重作日誌中,則在寫至磁盤以前要在重作緩衝區(redo buffer)中臨時緩存這些數據。當知足一下條件時,緩衝區數據會被刷出:
①每三秒
②commit
③切換日誌
④重作緩衝區1/3滿
⑤重作日誌數據緩存滿1M
redo緩衝區的默認大小隨操做系統和Oracle版本不一樣而不一樣,能夠經過查詢LOG_BUFFER這個參數來得到緩衝區的大小。
Oracle將數據庫塊寫至磁盤以前,或者從磁盤讀取數據庫塊以後,會把這些數據庫塊存儲在塊緩衝區緩存(block buffer cache)中。若是過小,查詢會永遠都運行不完;若是太大,其餘程序的將沒有運行空間。
Oracle8.0以前只有一個塊緩衝區緩存。Oracle8.0以後,開始把SGA中各個段的以緩存塊放在3個位置上。
①默認池(default pool):全部段塊通常都在這個池中緩存。
②保持池(keep pool):通常來講,訪問至關頻繁的段會放在這個候選的緩衝區池中,若是把這些段放在默認緩衝區池中,儘管會頻繁訪問,但仍有可能由於其餘段須要空間而被刷出。
③回收池(recycle pool):通常來講,訪問很隨機的大段能夠放在這個候選的緩衝池中,這些塊會致使過量的緩衝區刷新輸出,而當你想要在用這個塊時,它可能已經老化退出了緩存。要把這些段與默認池和保持池的段分開,這樣就不會致使默認池和保持池中的塊老化而退出緩存。
理論上講,默認池中的對象應該足夠熱,能夠保證一直呆在緩存中。
從Oracle9i開始,除了默認池、保持池和回收池外,還有第4種可選的緩存:db_Nk_caches。增長這些緩存是爲了支持數據庫中多種不一樣的塊大小。在Oracle Database 9i以前,數據庫中只有一種塊大小(通常是2KB、4KB、8KB、16KB、32KB)。從Oralce Database 9i開始,數據庫能夠有一個默認的塊大小,也就是默認池、保持池或回收池中存儲的塊的大小,還能夠有最多4種非默認的塊大小。
(1)在緩衝區緩存中管理塊
每一個池中的塊管理方式是同樣的。緩衝區緩存中的塊實際上在一個位置管理,但有兩個列表指向這些塊:
①髒塊(dirty)列表:其中的塊須要由數據庫塊寫入器(DBWn)寫入磁盤。
②非髒(nondirty)塊列表。
Oracle 8.0以前非髒塊列表就是最近最少使用(Least Recently Used,LRU)列表。塊按使用的順序列出。在Oracle 8i及之後的版本中,再也不按物理順序來維護塊列表,Oracle採用了一種接觸計數(touch count)算法,若是命中緩存中的一個塊,則會增長與之相關聯的計數器。
管理這些列表的整個算法至關複雜,並且隨着Oracle版本的變化也在變化,並不斷改進。咱們只要知道頻繁使用的塊會被緩存,不常使用的塊不會緩存過久。
(2)多個塊大小
每一個不一樣的塊大小都必須有其本身的緩衝區緩存。不一樣塊大小的緩衝區緩存不共享。默認池、保持池和回收池只緩存具備默認大小的塊。爲了在數據庫中使用非默認的塊大小,須要配置一個緩衝區池來保存這些塊。
例如:建立一個塊大小爲16KB的表空間
##首先建立16KB塊緩衝區緩存
SYS@drz>alter system set db_16k_cache_size = 16m scope=spfile;
System altered.
SYS@drz>startup force;
ORACLE instance started.
Total System Global Area 835104768 bytes
Fixed Size 2257840 bytes
Variable Size 532679760 bytes
Database Buffers 293601280 bytes
Redo Buffers 6565888 bytes
Database mounted.
Database opened.
##建立16KB塊的表空間
SYS@drz>create tablespace ts_16k datafile '/u01/app/oracle/oradata/drz/ts0
1.dbf' 2 size 16m
3 blocksize 16k;
Tablespace created.
共享池是Oracle緩存一些「程序」數據的地方。在解析查詢時,解析獲得的結果會緩存在這裏。Oracle把系統參數存儲在共享池中。數據字典緩存也存儲在這裏。
共享池的特色是有大量的小內存塊,通常是4KB或更小,這樣作的目的是爲了減小內存的碎片問題。共享池中的內存根據LRU(最近不多使用)的原則來管理。可使用DBMS_SHARED_POOL,來強制「盯住」共享池中的對象。
綁定變量對於提升共享池性能是很重要的。
大池(Large pool):用於存放大塊內存的分配。大池是一個回收型的空間。
大池專門用於如下狀況:
①共享服務器鏈接:用於在SGA中分配UGA區。
②語句的並行執行:容許分配進程間的消息緩衝區,這些緩衝區用於協調並行查詢服務器。
③備份:在某些狀況下用於RMAN磁盤I/O緩衝區。
Java池(Java pool):在Oracle8.1.5中增長的,目的是支持在數據庫中運行Java。若是用Java編寫一個存儲過程,Oracle會在處理代碼時使用Java池的內存,參數爲JAVA_POOL_SIZE。
由於專用服務器鏈接模式下,UGA在PGA中分配,共享服務器鏈接模式下,UGA在SGA中分配。因此專有服務器模式下的Java pool只包含每一個Java類的共享部分,內存相對較小;當使用共享服務器模式時,Java pool包含如下部分:
① 每一個Java類的共享部分;
② UGA 中用於各會話狀態的部分。UGA餘下的部分會正常的在共享池中分配,或者若是配置了大池,就會從大池中分配。
流池(stream pool):是一個新的SGA結構,從Oracle 10g開始新增的。流(stream)這個概念是在Oracle 9iR2及以上版本中才有的。流是數據庫的共享/複製工具。流池用於緩存流進程在數據庫間移動或者複製數據時使用的隊列消息。流使用的是內存中的隊列,若是這些隊列滿了,最終仍是會寫出到磁盤。若是使用內存隊列的Oracle實例因爲某些緣由失敗了,就會從重作日誌中重建這些內存中的隊列。
在有流池特性的數據庫版本中,若是沒有配置流池,則流池會從共享池中分配最多10%的空間。
Oracle 10g開始 管理SGA內存也有兩種方式:手動管理和自動管理。手動管理須要設置全部必要的池和緩存參數,自動管理則只需設置少數幾個內存參數和一個SGA_TARGET參數。經過設置SGA_TARGET參數,實例就能設置各個SGA組件的大小以及調整他們的大小。
在Oracle 10g中,與內存相關的參數能夠歸爲兩類:
①自動調優的SGA參數:目前這些參數包括db_cache_size/shared_pool_size/large_pool_size和java_pool_size。
②手動SGA參數:這些參數包括log_buffer/streams_pool/db_nk_cache_size/db_keep_cache_size和db_recycle_cache_size。
在Oracle 10g及更高版本中,能夠經過查詢v$sgainfo來查詢SGA的哪些組件大小能夠調整。
SYS@drz>select * from v$sgainfo;
採用自動SGA內存管理時,肯定自動調整組件大小的主要參數是SGA_TARGET,這個參數能夠在數據庫啓動並運行時動態調整,最大能夠達到SGA_MAX_SIZE參數值。
從Oracle 11gR1開始,Oracle數據庫開始使用自動內存管理。只須要設置memory_target,這個參數表示SGA和PGA的總量。數據庫會根據工做負載自動調整兩者大小。咱們也能夠設置SGA_TARGET和PGA_AGGREGATE_TARGET,爲各個內存區的大小設定下界,能夠經過修改轉儲參數文件spfile來實現修改。
PGA(進程全局區)是特定於進程的一段內存,也就是一個操做系統進程或線程專用的內存,不容許系統中的其餘進程和線程訪問。PGA通常經過C語言的運行時調用malloc()或memmap()來分配,並且能夠在運行時動態擴大。PGA不會從SGA中分配,而是經過進程或者線程在本地分配。PGA中的P表明Process,是不共享的。
UGA(用戶全局區)是會話訪問的的一塊內存。當使用共享服務器鏈接時,UGA須要存儲在每一個共享服務器進程都能訪問的一個內存結構中,也就是SGA中。當使用專用服務器鏈接時,再也不須要全部會話都能訪問你的會話狀態,UGA從PGA中分配。
PGA包含進程內存,還可能包含UGA。PGA內存中的其餘區一般用於完成內存中的排序、位圖合併以及散列。
從Oracle 9i起,有兩種方式來管理PGA中的非UGA內存:
①手動PGA內存管理
②自動PGA內存管理
從Oracle 11g開始,自動PGA內存管理能夠用如下兩種方式:
①經過設置PGA_AGGREGATE_TARGET初始化參數
②經過設置MEMORY_TARGET初始化參數
① SORT_AREA_SIZE:在信息換出到磁盤以前,用於對信息排序的RAM總量。
② SORT_AREA_RETAINED_SIZE:排序完成後用於保存已經排序的數據的內存總量。也就是說,若是SORT_AREA_SIZE是512KB,SORT_AREA_RETAINED_SIZE是256KB,那麼服務器進程最初處理查詢時會用512KB的內存對數據排序。等到排序完成後,排序區會「收縮」爲256KB,這256KB內存中放不下的已排序數據會寫出到臨時表空間中。
③HASH_AREA_SIZE:服務器進程在內存中存儲散列表所用的內存量。散列聯結時會使用這些散列表結構,一般把一個大集合與另外一個集合聯結時就會用到這些結構。兩個集合中較小的一個會散列到內存中,散列區中放不下的部分都會經過聯結鍵存儲在臨時表空間中。
SORT_AREA_SIZE減掉SORT_AREA_RETAINED_SIZE所得的這部份內存通常從PGA中分配,SORT_AREA_RETAINED_SIZE這部份內存會在UGA中分配。經過查詢動態性能視圖(dynamic performance view)能夠查看PGA和UGA內存的當前使用狀況。
自動PGA內存管理再也不使用SORT_AREA_SIZE、BITMAP_MERGE_AREA_SIZE和HASH_AREA_SIZE這些參數,引入自動PGA內存管理是爲了解決一下問題:
① 易用性。
②自動管理能夠根據工做負載動態地調整實際使用的內存量。
③內存控制。
須要調整一下兩個參數:
① WORKAREA_SIZE_POLICY: 這個參數能夠設置爲MANUAL或者AUTO,若是是MANUAL,那麼咱們要使用排序區和散列區大小參數來控制分配的內存量;若是是AUTO,分配的內存量會根據數據庫中的當前工做負載而變化。默認值是AUTO。
② PGA_AGGREGATE_TARGET: 這個參數會控制實例爲完成數據排序和散列的全部工做區(排序區和散列區)總共應分配多少內存。在不一樣的版本中,這個參數的默認值有所不一樣,可使用多種工具來設置,如DBCA。通常來講,若是使用自動PGA內存管理,就應該顯式的設置這個參數。