溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么理解Oracle Buffer

發布時間:2021-11-09 14:56:34 來源:億速云 閱讀:184 作者:iii 欄目:關系型數據庫

這篇文章主要介紹“怎么理解Oracle Buffer”,在日常操作中,相信很多人在怎么理解Oracle Buffer問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”怎么理解Oracle Buffer”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

一個Oracle Buffer是一個Oracle段對象緩存塊。一個Oracle buffer一開始時包含與Oracle塊中相同的信息。一個buffer的內容依賴于段類型以及它是滯是一個段頭塊。buffer有許多種狀態通過v$bh的state列來表示,它們可能被歸納成在種模式:free(可用),dirty(臟)與pinned(固定)。

Free Buffers
當一個buffer與磁盤上的數據塊匹配時它的狀態就是free。一個free buffer可以看作是一個鏡像buffer,因為它鏡像了磁盤上的數據塊。下面的查詢簡單的顯示了如何判斷buffer cache中free buffers的數量。一個free buffer可能確實是空的(例如,在實例重啟之后),但它將最有可能包含真實的塊信息,比如行記錄。一個free buffer可以被替換而不會產生任何損壞,因為有一個副本存儲在磁盤上。當然,如果一個事務提交,那么至少被修改的buffer必須被記錄到聯機重做日志文件中。

SQL> select count(*) from v$bh where status='free';
  COUNT(*)
----------
        24

一個free buffer可能不是被頻繁的訪問。也許一個查詢需要訪問單行數據因此需要將數據塊放入buffer cache中,而這個buffer之后再也沒有被訪問過。而另一方面,一個free buffer也可以是被頻繁訪問的。例如,如是一個特定的數據塊被重復地查詢,它將被頻繁的訪問,但它的狀態仍然是free狀態,因為buffer沒有被改變過。如果你對freebuffer的定義簡單又清晰,那么許多Oracle的算法將也變得清晰,這將使理解,檢測與解決競爭更容易。

Dirty Buffers
當一個buffer它不能與磁盤上的相關塊進行匹配時它的狀態就是dirty。對一個buffer進行的任何改變都會使用它的狀態變為dirty,因為buffer將不再與磁盤上的塊相匹配。當內存中的改變還沒有被寫入磁盤而要對其進行覆蓋時,dirty塊是不能被替換的。一旦數據庫寫進程將一個dirty buffer寫入磁盤,那么buffer將與磁盤上的塊再一次匹配那么這個buffer的狀態將變為free。

一個dirty buffer可能也不被頻繁訪問。假設一行記錄被修改但其它進程不需要訪問這個buffer。因為行記錄被改變這個塊確實是dirty的,但它不被頻繁訪問。當然,也有被頻繁訪問的dirty buffers。簡單地重復更新一行記錄將確保它的buffer的狀態為dirty又被頻繁的訪問。

下面的查詢顯示dirty buffers的狀態可能是xcur或write。將在cache buffer chains中詳細介紹current與consistent模式的buffers。xcur狀態意味著一個進程已經改變了一個current模式的buffer的狀態為這種狀態,并且進程可能現在更新buffer中的行記錄,雖然行記錄現在仍然受制于其它條件,比如行級鎖。排他模式不會阻止多個用戶改變相同buffer中的多行記錄,它簡單表示當current模式的buffer可以被改變。在RAC環境中這是至關重要的,可能有多個共享current模式buffers(scur),但在整個RAC數據庫中每個塊只有一個排他current模式buffer存在。

SQL> select status, count(*) from v$bh where dirty='Y' group by status;
STATUS       COUNT(*)
---------- ----------
xcur            20792
scur              919
pi               2567

Pinned Buffers
當一個buffer被pinned時,它不能被替換。另一種看待pinning的方式是對buffer的一種非官方鎖。因為一個buffer不是一種關系結構,標準的鎖機制不能應用。Pinning一個特定的buffer,latches或mutexes可以控制訪問整組buffers。Pinning可以與latch與lock一起連用來確保適當的序列化,保護與并行控制被實現。

假設一個服務器進程將要讀取一個buffer中的一行記錄。當你仍然在訪問這一行記錄時,有人使用其它的buffer替換了你正在訪問的buffer這是極端粗魯的。這就像你正在讀一本書時,有一個人說"讓我看看",并從你手中搶走一樣。許多進程可以pin相同的buffer(讀取相同的塊),但是只有一個進程能pinned這個buffer,它不能被替換。當一個free buffer的行記錄正被查詢時,它的狀態從free變為pinned再次回到free。當free buffer中的行記錄被修改后,它的buffer狀態將從free變為pinned,再變為dirty。

Oracle沒有通過v$bh視圖來顯示pinned buffers,但任何被touched的buffer也就是被pinned了。當一個buffer正被移動到寫列表中并且正更新touch計數時Oracle將也會pin這個buffer。

Buffer Headers的作用
當buffers內置在buffer cache中并且buffers確實已經被改變了,列表管理實際作用于buffer headers,而不是實際的buffers。一個buffer header是一個優化過的內存結構它包含關于一個buffer和與它相關的塊信息,但不包含塊數據比如行記錄。

為什么對于buffer cache沒有視圖v$bc?,這是因為一個buffer與一個塊的元數據被存儲在buffer header,并且它的元數據對于我們的性能分析是需要的。因此視圖被命名為v$bh,對于buffer header有三個關鍵的列表或鏈:
.Cache buffers chains(CBCs)被用來快速判斷一個Oracle塊是否內置在buffer cache中。

.最近最少使用(LRU)列被用來在cache中保留住被頻繁訪問的buffers并找到free buffers。

.寫列表包含不久將被寫入磁盤的dirty buffers。

重要的是理解buffer headers的這三個列表而不是實際的buffers。單個buffer header總是內置在一個CBC中和一個LRU鏈或一個寫列表中。

三個列表的維護是在buffer header級別,不是buffer級別,更不是在數據塊級別。我們許多人被教導當buffer內置在buffer cache中時,buffers它們本身是被鏈接的。這是不正確。每個buffer都與一個buffer header相關聯,并且在各種列表中操作的是buffer header。

Cache Buffer Chains
簡而言之,CBCs被用來回答“這個buffer是否在buffer cache中,如果在,它在哪里”這本質上是一個搜索類型的問題。很多類型的搜索算法可能被用來獲得答案:二叉樹,B+樹,B*樹,順序搜索,哈希算法,或一些算法組合。Oracle選擇使用一種哈希算法,緊接著使用快速順序搜索。

哈希算法
哈希算法可以非??焖?,因為整個結構通常被存儲在內存中并且要求一個單獨的數學計算,同時存在一些內存訪問來回答搜索問題。哈希結構有許多變化,但所有的哈希結構都是由一個哈希函數,哈希桶與哈希鏈組成的。

哈希函數
哈希函數接收輸入并使用定義的范圍來產生一個輸出。輸入被叫作一個哈希值。x mod 10函數可以簡單地被用來確保不管輸入的正數哈希值,它的輸出總是在0到9之間。哈希值輸入11,輸出將是1。一個好的哈希函數將會產生均勻分布的輸出。當Oracle將要搜索一個buffer時,基于數據塊的文件號與塊號的組合(它也叫數據塊地址DBA)來生成一個哈希值。因此哈希函數本質上是對buffer的數據塊文件號和塊號進行哈希運算。這是一種非常方便并可以快速哈希運算的情況。

哈希桶
哈希輸入值將被哈希到桶,每個輸出值代表了一個單獨的桶。在許多哈希情況下,可能輸入的哈希值的數量超過桶數。對于Oracle來說,可能的哈希輸出值就是Oracle數據塊的數量。但在任何情況下,哈希輸入值的數量將與buffercache中的buffers的數量相等。

當有兩個哈希值被哈希到相同的桶時,這叫作碰撞。碰撞對于哈希來說是很常見的。碰撞可以通過增加哈希桶的數量來最小化,但可能對于高性能程序來說是一種災難,比如Oracle數據庫。例如,假設x mod 10的哈希函數有1000哈希輸入值,這將肯定會出現碰撞。為了避免碰撞,哈希算法輸出完全均勻的輸出將需要1000個哈希桶。使用一種極好的哈希算法與大量的哈希桶兩種方法減少碰撞。如果哈希算法不變,那么可以增加哈希桶的數量。

哈希鏈
每個哈希桶都有一個相關聯的哈希鏈。當一個搜索的對象被哈希到一個桶時,這個桶的鏈被順序搜索來查找對象。如果對象在哈希鏈中沒有找到,我們知道對象不在整個哈希結構中。如果哈希鏈很短,順序搜索將很快完成。如是對象不在cache中,鏈長度最好為零。

Oracle的CBC結構是一種復雜的內存結構,并且Oracle必須要維持序列化控制。所以它使用了一種序列化結構:latch或mutex。

如何破壞CBC的性能
要學習如何解決性能問題的最好方法就是知道如何模擬問題,有三種典型的方法來降低CBC的性能:
.當減少latches的數量時,剩余latches的并發將會增加
.如果減少CBCs的數量,平均每個CBC的長度將會增加,剩余chains的并發與CBC的掃描時間也會增加
.如果buffer克隆變得激烈,那么頻繁訪問的chain將變得很長,會增加并發與CBC的掃描時間

減少latches來限制并發
使用單個latch,序列化將被保證,但是并發性將受到嚴重的限制。當另一個進程請求latch時而它被其它進程所持有時就會產生競爭。在這個例子中,簡單地增加一個latch可以解決這個問題。如果存在上百成千個進程需要訪問CBCs,那么可以看到存在嚴重的并發性能限制問題。幸運地是缺省情況下Oracle創建了上百個CBC latches。

Oracle知道它的哈希函數不完美并且將會產生碰撞。一種減少碰撞的方法是有大量的CBCs。但你第一反應會覺得更多的CBCs將會消耗更多的內存,但事實不是這樣的。每個buffer header必須內置在一個CBC鏈上,與CBC鏈的數量及長度無關。當使用更多的CBC鏈時,而buffer headers的數量不變時,平均CBC鏈的長度會減小。因此,對于每個CBC鏈雖然有一些額外的內存消耗,但真正的內存消耗者是buffer headers的數量,不僅僅是CBC鏈的數量。

許多年以前規則定義latches的數量不應該超過CPU核數的兩倍。很明顯Oracle已經修改了規則,CBC latches只是Oracle數據庫中許多latches中的一種。

Oracle可能處理多個CBC latches,有人會認為對于每個CBC將有一個latch,但Oracle認為這是不必要的且一個latch可以管理上百個CBC鏈。

如果CBC鏈比buffers多,這意味著有一些CBC鏈將不會關聯buffer header,這將有效的使CBC鏈的長度變為零。

[oracle@jytest2 ~]$ sqlplus / as sysdba
SQL*Plus: Release 12.2.0.1.0 Production on Thu Mar 21 10:28:02 2019
Copyright (c) 1982, 2016, Oracle.  All rights reserved.
Connected to:
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production
SQL> col param format a50 heading "Instance Param and Value" word_wrapped
SQL> col description format a20 heading "Description" word_wrapped
SQL> col dflt format a5 heading "Dflt?" word_wrapped
SQL> select rpad(i.ksppinm, 35) || ' = ' || v.ksppstvl param,
  2  i.ksppdesc description,
  3  v.ksppstdf dflt
  4  from x$ksppi i,
  5  x$ksppcv v
  6  where v.indx = i.indx
  7  and v.inst_id = i.inst_id
  8  and i.ksppinm in
  9  ('db_block_buffers','_db_block_buffers','db_block_size',
 10  '_db_block_hash_buckets','_db_block_hash_latches'
 11  )
 12  order by i.ksppinm
 13  /
Instance Param and Value                           Description          Dflt?
-------------------------------------------------- -------------------- -----
_db_block_buffers                   = 97136        Number of database   TRUE
                                                   blocks cached in
                                                   memory: hidden
                                                   parameter
_db_block_hash_buckets              = 262144       Number of database   TRUE
                                                   block hash buckets
_db_block_hash_latches              = 8192         Number of database   TRUE
                                                   block hash latches
db_block_buffers                    = 0            Number of database   TRUE
                                                   blocks cached in
                                                   memory
db_block_size                       = 8192         Size of database     FALSE
                                                   block in bytes

引起CBC latch競爭的最好和最簡單的方法之一就是創建一個大的buffer cache來緩存更多的塊,然后將CBC latches的數量減少到一個。Oracle從10g開始就不允許CBC latches的數量小于1024,但是即使有1024個CBC latches和足夠的邏輯IO能力,也能經??吹紺BC latch競爭。

通過減少CBC的數量來增加CBC的掃描時間
如果CBCs很長,那么掃描它的時間將會引起顯著的競爭。另外其它進程獲得CBC latch的時間也會顯著增強。一種很明顯的方式是增加平均每個CBC的長度來減少CBC的數量,這可以通過減少哈希桶的數量來完成。簡單地將實例參數_db_block_hash_buckets減少到50,確保你查詢的塊內置在buffer cache中,那么會很快得到CBC latch競爭。因為Oracle至少要確保64個哈希桶來忽略你的設置,但這仍然會有大量的競爭。

在現實中,一種解決CBC latch競爭的方法是增加哈希桶的數量,這將減少平均每個CBC的長度。如果一個特定的CBC很長且被頻繁文章,那么這個解決方案將不能提高性能。此外Oracle創建了大量的CBC,因此增加哈希桶的數量不像增加CBC一樣能顯著的提高性能,但它有一種有效的方法應該值得考慮。

使用克隆Buffers來增加CBC的掃描時間
雖然長CBC的問題很少見,但如果出現了,那么情況是很嚴重的。理解這是如何發生的不僅僅可以幫助你解決這個問題還能更深入的理解CBCs,latch,undo與讀一致性。它涉及RAC系統。

長CBC代表了一個非常有挑戰性的問題。首先,哈希結構是很快速的因為幾乎沒有掃描,因此長CBC會迅速降低使用哈希算法的好處。第二,一個掃描進程必須處理一個CBC latch,不是隨便一個CBC latch,這個CBC latch保護特定的CBC。一個長CBC意味著CBC latch將被持有更長時間并且當掃描列表將使用更多的CPU。另外,因為CBC latch被持有的時間更長,這將增加另外的進程競爭latch的可能性。當競爭latch的進程在spinning與在sleeping時發布等待事件時都是要消耗CPU的。但問題遠不止如此。

正常情況下,Oracle的哈希算法使用的CBC的數量是buffers的兩倍還多,因此CBC的長度很短。長CBC出現的唯一方式是多個buffers被哈希到相同的CBC上。通常這不是一個問題,但也可能出現。為了解析這種情況,先了解塊克隆與哈希。當一個Oracle塊被cached后,只有單個當前模式buffer能被修改。如果buffer中的一行需要被修改,單個當前模式buffer必須是可用的。當前模式buffers有時也叫CU buffers。在RAC系統中,如果需要的當前模式buffer內置在另一個實例中,那它必須被發送到你使用的這個實例中然后才可以修改buffer。

假設一個服務器進程在時間T100正運行一個查詢。這個進程訪問數據字典并知道它將必須訪問一個特定塊,因此它將被哈希到合適的CBC,獲取合適的CBC latch,掃描CBC,并找到當前模式buffer的buffer header。然而在檢查buffer header時,發現當前模式buffer在時間T200被修改過,是在服務器進程開始執行查詢之后。這意味著在查詢執行后需要的行記錄已經被修改過了。 Oracle的缺省讀一致性模式要求被返回的信息與查詢開始執行時的一致。因此Oracle必須采取操作來確保被返回的信息對于時間T100來說是正確的。

Oracle現在要么找到一個buffer的副本,要么構建一個當前模式buffer的副本,因此這個buffer代表了時間T100所處處的情況。一個buffer副本通常叫做buffer克隆??寺∫粋€buffer是一種相對昂貴的處理。首先,必須找到一個free buffer,然后buffer header必須被合適的連接到CBC結構與LRU鏈結構。

理解潛在的重大性能影響的關鍵是理解被克隆的buffer的buffer header將內置在CBC結構中的什么位置。因為被克隆的buffer是一個合法的buffer,它在buffer cache中占據了空間,能被共享且必須被定位。這意味著它必須被合適的內置在CBC結構中。被克隆的buffer的文件號與塊號與它的當前模式buffer的相同,這意味著它必須被哈希到相同的CBC。因此,如果一個buffer有50個克隆副本,與它相關的CBC將至少有50個buffer header那么長,并且如果與其它buffer出現碰撞可能更長。Oracle對此無能為力,因為哈算法是基于文件號與塊號的。

不僅free buffer搜索算法有利于替換克隆的buffer,但Oracle試圖限制每個buffer的克隆數量。Oracle想要每個buffer的克隆數量不超過隱含參數_db_block_max_cr_dba,它的缺省值為6。然而如果克隆變得很激烈,一個buffer的克隆副本很容易超過6個。

SQL> col name for a30
SQL> col value for a20
SQL> col describ for a50
SQL> select x.ksppinm NAME,y.ksppstvl value,x.ksppdesc describ
  2  from x$ksppi x, x$ksppcv y
  3  where x.inst_id=USERENV('Instance')
  4  and y.inst_id=USERENV('Instance')
  5  and x.indx=y.indx
  6  and x.ksppinm like '%&par%';
Enter value for par: _db_block_max_cr_dba
NAME                           VALUE                DESCRIB
------------------------------ -------------------- --------------------------------------------------
_db_block_max_cr_dba           6                    Maximum Allowed Number of CR buffers per dba
1 row selected.

有許多克隆的buffer不一定意味著有性能問題。如果真的出現性能問題,CBC latch競爭問題將非常明顯。如果出現這種情況并發現克隆buffer的問題,那么考慮以下可能的補救措施:
.修復應用程序
這通常是必須要做的。這是非常痛苦的,需要開會,如果應用程序開發者參與將會非常專業化,并且通常要求應用程序以某些方式被修改來減少單個克隆buffer被頻繁的訪問。

.移動行記錄
如果幸運的話,可能存在多行記錄使得buffer被頻繁訪問。如果可能散這些行,因此多個buffer現在不再被頻繁的訪問。當修改傳統的pct_free與pct_used存儲參數是一種選擇時,為了增加控制,可以考慮設置一個塊可以存儲的最大記錄數。意外地是這不僅僅是簡單地執行類似于alter table all_status minimizer records_per_block 5語句

.平衡工作負載
如果能控制工作負載強度,在克隆活動高峰期間,考慮減少與buffer克隆活動相關的工作負載。雖然這不是一個令人興奮的解決方案,工作負載平衡也能對性能產生積極影響。

CBC競爭識別與解決方案
一些解決方案可以幫助你解決CBC競爭的問題。在嘗試解決CBC latch問題之前,確保它們存在。

SQL> @swpctx
Remember: This report must be run twice so both the initial and
final values are available. If no output, press ENTER twice.
DB/Inst: RLZY/RLZY1                                               25-Mar 11:24am
Report:   swpctx.sql           OSM by OraPub, Inc.                Page         1
            System Event CHANGE (17 sec interval) Activity By PERCENT
                                       Time Waited  % Time    Avg Time     Wait
Wait Event Display Name                      (sec)  Waited Waited (ms) Count(k)
-------------------------------------- ----------- ------- ----------- --------
latch: cache buffers chains                 10.610   96.28        15.7        1
control file parallel write                  0.160    1.45         7.6        0
log file parallel write                      0.030    0.27        15.0        0
log file sync                                0.000    0.00         0.0        0

如果數據庫系統是Oracle 10g之前的版本,那么top wait event將會是latch free,就需要確認latch問題是CBClatch。對于Oracle 10g及以后的版本,wait event將是latch: cache buffers chains。在大多數情況下,CPU子系統將被大量利用并且負擔過重。以下是可能的CBC latch解決方案:
.優化邏輯IO SQL語句
當回答“buffer是否在buffer cache”中時CBC結構將變得緊張起來,期待的答案總是“Yes”,如果答案為“No”,將會看到順序讀或分散讀等待事件。因此從應用程序角度來看,查找執行活動主要是buffer gets也就是邏輯IO的SQL盡你所能地減少邏輯IO消耗。這是典型的SQL優化,包括索引,以及在性能問題出現時減少執行速率。

.增加CPU處理能力
在大多數情況下,CPU子系統將被過多利用并且可能是操作系統瓶頸。latch的獲得與相關的內存管理可能消耗過多的CPU資源。做任何可以減少CPU消耗與能增加CPU能力的事。查找在高峰期間沒有執行或正在執行的進程??紤]增加或者使用更快的CPU。如果正在運行在虛擬環境中,考慮確保Oracle系統已經增加CPU資源。然而,請注意除非應用程序工作負載已經顯著增加,增加的CPU處理能力通常將被快速地消耗掉。真正的解決方案可能是其它的方案。增加CPU能力可能是一個快速解決方案,但它可能不能真正地解決問題。

.檢查buffer克隆問題
無論何進遇到CBC latch競爭問題,都需要檢查是否存在buffer克隆的問題。這是很少見的情況,但如果遇到了,那么解決方案與其它解決方案是非常不同的。

.增加CBC latch數量
這通常會帶來一些安慰,但不是真正的優化邏輯IO SQL。隱含參數_db_block_hash_latches控制著CBC latch的數量

.增加CBC buckets
它很難對性能產生影響,因為Oracle缺省情況下,創建了大量的buckets。除非之前減少了CBC buckets的數量,增加這個參數的大小將會顯著地影響性能。

到此,關于“怎么理解Oracle Buffer”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女