解析
shared pool
圖解:
library cache裡面,暫時可以認為儲存著:
1、SQL以及對應的執行計劃(所佔空間比較小);
2、儲存過程、函式、觸發器、包,它們編譯後的物件(所佔空間往往比較大,特別是包所佔的比較大)
對於shared pool管理和研究的時候,row cache一般不會出現問題,所以一般情況我們都不研究row cache,會出問題的經常是library cache,所以我們經常研究它
如果要執行包裡面的一個儲存過程的時候,oracle就會把整個包頭(包規範)的部分調到library cache裡面去,這時候就可能造成比較大的一個物件突然被調到library cache裡去,這時候有可能會報4013錯誤;所以寫包的時候,儘量不要把過多的儲存過程或者函式放到一個包裡面去
在shared pool裡,有時候可能造成比較大的一個物件突然被調到library cache裡去,這時候有可能會報4013錯誤,所以為shared pool專門設了一個,一個比較大的物件突然被調到library cache裡去的空間:reserved空間,用來儲存突然來的大物件的空間,佔shared pool空間大小的5%,
假設library cache的大小為5G,快取著大量的SQL以及SQL的執行計劃,現在,要去執行一個SQL,就在library cache裡面的這些大量的SQL以及SQL的執行計劃裡面找,這就有一個問題,該怎麼找呢?假設library cache裡面有100萬行,然後一個一個去對比,就要找100萬次,這顯然就不合適;
管理SQL以及SQL的執行計劃
鏈(chain)
那麼library cache裡面是如何組織和管理SQL以及SQL的執行計劃的,以便於很方便的找到要執行的SQL?
圖解:
用鏈把一個一個的SQL鏈起來,假設library cache有500M大小,用4個鏈來管理SQL;對於SQL1來說:SQL1經過hash以後,得到hash值,然後計算:hash值/4的餘數(0、1、2、3......):如果餘數 = 0,就把SQL1掛在0號鏈上;如果SQL1在library cache裡面,server process就認為SQL1一定在0號鏈上,然後在0號鏈上找,不需要在另外的鏈上找;另外假設SQL2,經過hash,然後計算餘數,假設餘數 = 1,就在1號鏈上找,最終沒有找到,它就不找了,因為也不可能在其他的鏈上,然後SQL2就要產生硬解析了
鏈的特點:
1、鏈的一種訪問方式:只能遍歷,不能隨機訪問(找到鏈的頭部就可以一個一個的找,一直找到鏈的尾部)
2、一種鏈一種作用(比如SQL經過hash,然後掛在鏈上的,找的時候也是SQL經過hash然後在鏈上找)
library cache裡面的鏈:就是SQL經過hash值的方式掛起來的(當初怎麼組織的,找的時候就怎麼找)
library cache的大小,會影響鏈的數量(library cache多大,鏈的數量是多少,這個是oracle自己去調整、適應的;我們也可以調整相關的引數來調整鏈的數量)
一個鏈可以認為是一個bucket(桶)
Hash(其實就是一個函式)
例如對於SQL:select name from t where id = :x;
oracle會把SQL語句裡面的每一個字母,轉換成一個ASCII碼值,每一個字母對應著一個編碼,
一個SQL --> 一堆的文字字母 --> 一堆的數字
hash值與SQL的幾種對應關係:
1、如果SQL1和SQL2完全相同,那麼它們的hash值一定相等
2、如果SQL1和SQL2不相同,那麼它們的hash值一定不相等
3、如果SQL1和SQL2的hash值相等,但是SQL1和SQL2不一定相同
所以比較兩個SQL時:
1、如果兩個SQL的hash值不相等,那麼兩個SQL就不相;
2、如果兩個SQL的hash值相等,那麼還要比較兩個SQL,一個字母一個字母的去比較
free空間
free裡面的chunk是如何管理的?
也是使用鏈來管理的
從free空間裡面找空閒的chunk(記憶體塊),怎麼找?
根據大小來找;比如現在我們需要一個4k大小的,就在free裡面找一個4k的chunk,不行就找比4k大一點點的(比如:5k、8k、12k),然後找5k的,所以free裡面是透過一種以free chunk的大小的鏈把一個一個的chunk掛在上面的
圖解:
有三個鏈:2k、8k、16k,現在需要一個9k的,就在8k的鏈上找,找到一個12k的,可以,就用一下,用了9k還剩下3k,又掛到2k的鏈上。
遊標(cursor)
一個SQL以及SQL對應的執行計劃,叫做一個cursor,在library cache裡面
父遊標(parent cursor)
父遊標說的是:SQL文字;同一個SQL可能對應多個執行計劃(因為訪問的使用者不同,表的名字一樣(都是t表),但是表的內容不一樣;或者因為繫結引數的值的不同(同一個值,一個表裡有1000萬行,另外一個表裡只有10行(這裡表的名字相同)),執行計劃也可能不同)
子游標(children cursor)
子游標就是:執行計劃;子游標的個數不定,根據實際情況而定(比如10個、100個不確定)
version count(版本數量)
例如一個父遊標有10個子遊標,那麼它的版本數量就是10
latch:鎖(記憶體鎖、閂鎖),用來保護鏈的
圖解:
現在有一個問題:oracle有好多上的server process,;假設server process1執行SQL1,server process2執行SQL2,然後server process1執行SQL1的時候要解析,在library cache裡面沒找到,SQL1就要發生硬解析;執行SQL2的時候,同樣也如此,SQL2也需要硬解析;同時解析;
在解析的時候,就需要在free裡面找一個free chunk,把它寫進去;假設解析SQL1需要一個,9k的free chunk,解析SQL2,需要一個10k的free chunk,所以都需要在8k的鏈上找,這就有一個併發的問題:假設SQL1和SQL2找到相鄰的兩個free chunk;SQL1就要把它找到的free chunk2拿下來,把free chunk1指向free chunk3;SQL2把找到的free chunk3拿下來,然後把free chunk2指向free chunk4;這時候,free chunk2和free chunk3都沒了,鏈就斷了,所以對於這種情況鏈就需要併發保護,使用鎖(latch)來進行保護;
latch(對於0號鏈申請的一個記憶體結構),用來保護0號鏈的,現在server process1讀這個latch(裡面有沒有寫相關資訊),發現裡面是空的,server process1就以S的方式寫上,server process1以S的方式來訪問0號鏈;
latch裡面是空的,說明沒有程序來對這個鏈進行保護修改;然後server process2也要來訪問0號鏈,發現有一個程序在以S的方式訪問,server process2想加一個X方式,但是server process1以S的方式持有著latch,server process2也想持有著latch,但是S和X不相容,所以server process2就不能持有著latch,這時候server process2就發生一次latch misses(latch丟失);
假設server process1在cpu1上工作,server process2在cpu2上工作(有兩個cpu),這時候,還有一個server process3在等著cpu空出來再進去,現在對於server process3來說兩種選擇:
1、server process2退出來(latch丟失),再進入cpu2,server process3工作一段時間以後退出來,server process2再進去,繼續執行之前未執行完的操作,這個過程叫做:context switch(CS);
2、server process1持有latch的時間非常短,很短的時間內就執行完了,這時候,server process2不出來,它執行一個for迴圈,佔用著cpu2,等server process1執行完S之後釋放了latch就進去,這時候server process3就可以使用cpu1了;
再有假設,有四個cpu,server process2不出來,佔用著cpu2,這時候server process3也持有著latch,server process2又再一次latch丟失了,然後server process4又持有著latch,server process2空轉cpu,server process2又再一次latch丟失,server process2多次latch丟失以後,server process2就轉為sleep狀態,然後就退出cpu了,其他的server process就可以佔用這個cpu了
因此,如果資料庫出現嚴重的latch徵用,就會表現出cpu很繁忙
sleep狀態,說明出現了多次latch misses(latch丟失)
當server process1想訪問0號鏈的時候,有兩種訪問方式:
1、S(共享鎖)的方式(讀鏈,在鏈上找大小)
2、X(排他鎖)的方式(修改鏈,就是往鏈上掛東西和往鏈上摘東西)
S方式和X方式的關係
例如:1、SQL1:S 2、SQL1:S 3、SQL1:X
SQL2:S SQL2:X SQL2:S
1、SQL1和SQL2可以同時進行(S、S可以相容)
2、SQL1和SQL2不能同時進行,要等SQL1找完了,SQL2再去修改(S、X不相容)
3、SQL1和SQL2不能同時進行,要等SQL1修改完了,SQL2再去找(S、X不相容)
latch的另外一種情況:
多個鏈用一個latch來保護,就很有可能出現latch丟失,所以我們可以透過調整引數來讓多個鏈讓多個latch來保護
latch的種類(絕大部分):
1、父latch:library cache latch
2、子latch:每一個鏈上latch(library cache latch裡面一個一個的latch)
latch的工作方式:
1、sp1:S方式持有著latch
sp2:X方式,出現latch misses,空轉著cpu,多次latch misses以後,變為sleep狀態
2、sp1:S方式持有著latch 0
sp2:X方式,也想持有著latch 0,出現latch misses;但是sp2從latch 0上的鏈上能找到想要的東西,從latch 1上的鏈上也能找到想要的東西,一樣;這時候,sp2就跑到latch 1去找東西了
但是絕大多數都是以第一種工作方式(willing to waiter)工作:願意等,或者必須等的