Oracle體系架構:系統全局區SGA
最新學訊:近期OCP認證正在報名中,因考試人員較多請盡快報名獲取最近考試時間,報名費用請聯系在線老師,甲骨文官方認證,報名從速!
我要咨詢SGA(System Global Area, SGA)是一組共享內存結構, 被所有的服務和后臺進程所共享。當數據庫實例啟動時,系統全局區內存被自動分配。當數據庫實例關閉時,SGA內存被回收。 SGA是占用內存最大的一個區域,同時也是影響數據庫性能的重要因素。
查詢SGA區的情況:
SQL> show SGA Total System Global Area 3290345472 bytes Fixed Size 2217832 bytes Variable Size 1795164312 bytes Database Buffers 1476395008 bytes Redo Buffers 16568320 bytes SQL> select * from v$sga; NAME VALUE -------------------- ---------- Fixed Size 2217832 Variable Size 1795164312 Database Buffers 1476395008 Redo Buffers 16568320
Fixed Size表示固定區域,存儲SGA各個組件的信息。不能修改大小。
Variable Size表示可變區域,比如共享池、java池、大池等。
Database Buffers表示數據庫高速緩沖區。
Redo Buffers表示日志緩沖區。
固定SGA(Fixed SGA)
固定SGA:顧名思義,是一段不變的內存區,指向SGA中其他部分,Oracle通過它找到SGA中的其他區,可以簡單理解為用于管理的一段內存區。
塊緩沖區(Database buffer cache)
數據高速緩沖區(Database Buffer Cache):用于存放從數據文件讀取的數據塊,由初始化參數DB_CACHE_SIZE決定。
工作原理和過程是 LRU(最近最少使用 Least Recently Used )。查詢時,Oracle會先把從磁盤讀取的數據放入內存供所有用戶共享,以后再查詢相關數據時不用再次讀取磁盤。插入和更新時,Oracle會先在該區中緩存數據,之后批量寫到硬盤中。通過塊緩沖區,Oracle可以通過內存緩存提高磁盤的I/O性能(注:磁盤I/O的速率是毫米級的,而內存I/O的速率為納秒級)
數據高速緩存塊由許多大小相等的緩存塊組成,這些緩存塊的大小和OS塊大小相同。 這些緩存塊分為3大類
臟緩存塊( Dirty buffers ):臟緩存塊中保存的時被修改過的緩存塊。即當一條SQL語句對某個緩存塊中的數據進行修改后,該緩存塊就被標記為臟緩存塊。最后該臟緩存塊被DBWn進程寫入到硬盤的數據文件中,永久保留起來。
命中緩存塊( Pinned buffers ):命中緩存塊中保存的是最近正在被訪問的緩存塊。它始終被保留中數據高速緩存中,不會被寫入數據文件。
空閑緩存塊(Free buffers):該緩存塊中沒有數據,等待被寫入數據。oracle從數據文件中讀取數據后,尋找空閑緩存塊,以便寫入其中。
Oracle 通過 2 個列表(DIRTY、LRU)來管理緩存塊
1、DIRTY 列表中保存已經被修改但還沒有被寫入到數據文件中的臟緩存塊。
2、LRU列表中保存所有的緩存塊(還沒有被移動到DIRTY列表中的臟緩存塊、空閑緩存塊、命中緩存塊)。當某個緩存塊被訪問后,該緩存塊就被移動到LRU列表的頭部,其他緩存塊就向LRU列表的尾部移動。放在最尾部的緩存塊就最先被移出LRU列表。
數據高速緩存的工作原理過程是:
A、ORACLE在將數據文件中的數據塊復制到數據高速緩存中之前,先在數據高速緩存中找空閑緩存塊,以便容納該數據塊。Oracle 將從LRU列表的尾部開始搜索,直到找到所需的空閑緩存塊為止。
B、如果先搜索到的是臟緩存塊,將該臟緩存塊移動到DIRTY列表中,然后繼續搜索。如果搜索到的是空閑緩存塊,則將數據塊寫入,然后將該緩存塊移動到DIRTY列表的頭部。
C、如果能夠搜索到足夠的空閑緩存塊,就將所有的數據塊寫入到對應的空閑緩存塊中。則搜索寫入過程結束。
D、如果沒有搜索到足夠的空閑緩存塊,則ORACLE就先停止搜索,而是激活DBWn進程,開始將DIRTY列表中的臟緩存塊寫入到數據文件中。
E、已經被寫入到數據文件中的臟緩存塊將變成空閑緩存塊,并被放入到LRU列表中。執行完成這個工作后,再重新開始搜索,直到找到足夠的空閑緩存塊為止。
這里可以看出,如果你的高速緩沖區很小的,不停地寫寫,造成很大I/O開銷。
塊緩沖區可以配置1、2或3個緩沖池,默認只有一個
默認池(Default pool):所有數據默認都在這里緩存,除非你在建表的時候指定 Store(buffer_pool keep) or Store(buffer_pool recycle)。使用LRU算法管理。
保持池(Keep pool):緩存需要多次重用的數據,長期保存內存中,缺省值為0。
回收池(Recycle pool):用來緩存很少重用的數據,用完就釋放,缺省值為0。
原來只有一個默認池,所有數據都在這里緩存。這樣會產生一個問題:大量很少重用的數據會把需重用的數據“擠出”緩沖區,造成磁盤I/O增加,運行速度下降。后來分出了保持池和回收池根據是否經常重用來分別緩存數據。這三部分內存池需要手動確定大小,并且之間沒有共享。例如:保持池中已經滿了,而回收池中還有大量空閑內存,這時回收池的內存不會分配給保持池,這些池一般被視為一種非常精細的低級調優設備,只有所有其他調優手段大多用過之后才應考慮使用。
在9i之前,數據緩沖區的大小是由DB_BLOCK_BUFFER確定,之后的版本中,是由參數DB_CACHE_SIZE及DB_nK_CACHE_SIZE確定。不同的表空間可以使用不同的塊大小,在創建表空間中加入參數BLOCKSIZE指定該表空間數據塊的大小,如果指定的是2k,則對應的緩沖區大小為DB_2K_CACHE_SIZE參數的值,如果指定的是4k,則對應的緩沖區大小為DB_4K_CACHE_SIZE參數的值,以此類推。如果不指定BLOCKSIZE,則默認為參數DB_BLOCK_SIZE的值,對應的緩沖區大小是DB_CACHE_SIZE的值
重做日志緩沖區(Redo log buffer)
用于存放日志條目,日志條目就是記錄對數據的改變。當這塊區域用光時,后臺進程LGWR把日志條目寫到磁盤上的聯機日志文件中。它由初始化參數log_buffer決定大小。同樣的道理下,日志緩沖區應該稍微大點,特別是有長時間運行的事務的時候,可以大量減少I/O。
數據寫到重做日志文件之前在這里緩存,在以下情況中觸發:
每隔3秒
緩存達到1MB或1/3滿時
用戶提交時
緩沖區的數據寫入磁盤前
共享池(Shared pool)
用于存放SQL語句、PL/SQL代碼、數據字典、資源鎖和其他控制信息。它由初始化參數SHARED_POOL_SIZE控制其大小。它包含以下幾個緩沖區:
1、 數據字典緩存(data dictionary cache),用于存儲經常使用的數據字典信息。比如(表的定義、用戶名、口令、權限、數據庫的結構等)。Oracle運行過程中經常訪問該緩存以便解析SQL語句,確定操作的對象是否存在,是否具有權限等。如果不在數據字典緩存中,服務器進程就從保存數據字典信息的數據文件中將其讀入到數據字典緩存中。數據字典緩存中保存的是一條一條的記錄(就像是內存中的數據庫),而其他緩存區中保存的是數據塊信息。
2、 庫緩沖區(Library Cache): 庫緩存的目的就是保存最近解析過的SQL語句、PL/SQL過程和包。這樣一來,Oracle在執行一條SQL語句、一段PL/SQL 過程和包之前,首先在“庫緩存”中搜索,如果查到它們已經解析過了,就利用“庫緩存”中解析結果和執行計劃來執行,而不必重新對它們進行解析,顯著提高執行速度和工作效率。
ORACLE將每一條SQL語句分解為可共享、不可共享的兩部分。
a) 共享SQL區:存儲的是最近執行的SQL語句、解析后的語法樹和優化后的執行計劃。這樣以后執行相同的SQL語句就直接利用在共享SQL區中的緩存信息,不必重復語法解析了。Oracle在執行一條新的SQL語句時,會為它在共享SQL區中分配空間,分配的大小取決于SQL語句的復雜度。如果共享SQL區中沒有空閑空間,就利用LRU算法,釋放被占用的空間。
b) 私用SQL區(共享模式時):存儲的是在執行SQL語句時與每個會話或用戶相關的私有信息。其他會話即使執行相同的SQL語句也不會使用這些信息。比如(綁定變量、環境和會話參數)。
3、 結果高速緩存:結果高速緩存包含 SQL 查詢結果高速緩存和 PL/SQL 函數結果高速緩存。此高速緩存用于存儲 SQL 查詢或 PL/SQL 函數的結果,以加快其將來的執行速度。
4、 鎖與其他控制結構:存儲ORACLE例程內部操作所需的信息。比如(各種鎖、閂、寄存器值)。
大池(Large pool)
大池由初始化參數LARGE_POOL_SIZE確定大小,可以使用ALTER SYSTEM語句來動態改變大池的大小,是可選項,DBA可以根據實際業務需要來決定是否在SGA區中創建大池。如果沒有創建大池,則需要大量內存空間的操作將占用共享池的內存, 將對SHARED POOL造成一定的性能影響,而LARGE POOL是起著這種功能隔離作用的一塊區域。
ORACLE 需要大量內存的操作有:
A、數據庫備份和恢復,如RMAN某些情況下用于磁盤IO緩沖區
B、具有大量排序操作的SQL語句
C、并行化的數據庫操作,存放進程間的消息緩沖區
D、共享服務器模式下UGA在大池中分配(如果設置了大池)
Java池(Java pool)
用于支持在數據庫中運行java代碼,一般由java_pool_size控制
流池(Stream pool)
加強對流的支持,一般由stream_pool_size控制。流池(或者如果沒有配置流池,則是共享池中至多10%的空間)會用于緩存流進程在數據庫間移動/復制數據時使用的隊列消息