oracle學習筆記 sharedpool內存塊組成結構及4031錯誤產生原因分析



oracle學習筆記

sharedpool內存塊組成結構及4031錯誤產生原因分析

sharedpool有三個空間
1、free
2、librarycache
它們容易出問題
3、rowcache
它不容易出問題。

我們只能總體上設sharedpool的大小,
不能設librarycache和rowcache分別佔多大,它們的大小我們控制不了,
oracle會根據實際的使用情況,自動設置這兩個的大小。

一)free空間內存的組成和組織管理

free空間不是一個大的控制內存塊,
它由很多被分爲不同大小的小內存塊組成,
並使用鏈結構來分類管理。
它們按大小不同串在不同的鏈上
鏈英文chain
塊英文chunk
即內存塊都被掛在鏈上
在free空間掛的都是free的空閒內存塊

每個鏈所掛的內存塊的大小是不一樣的。
從小到大形成一定的階梯
如一個鏈上掛的是4K的內存塊
一個鏈掛8k的,
一個鏈掛12k的。
4K鏈上的內存塊大小就大於等於4K而小於8K
8K鏈上的內存塊大小就大於等於8K而小於12K

解析一個sql語句時,
數據庫會根據解析的sql語句,和sql語句的執行計劃
計算出需要佔用的實際空間。
這時我們需要一個空閒塊,
如需要一個10K的空間
我們就在相應的8K的鏈上找10K的塊
找到一個11K的大小合適,
但只需10K,
就把11K的分成兩個 一個10K、一個1K
把sql語句和執行計劃寫到這個10K的塊中,
並把這個塊,放到librarycache中去。
剩下了一個1K的空閒內存塊,把它掛在free空間的1K的鏈上。

硬解析的時候會發生剛纔說的情況,
軟解析不需要從free空間找chunk


二)ora-4031錯誤的產生

硬解析也產生了一個問題,
產生了一些小chunk,即產生了碎片,如上面例子中產生的1K的空閒塊

如果數據庫系統裏面有大量的硬解析,
會發現雖然free裏面還有很多空間,
但是所有的空間都是小的,不能使用。
如一個sql語句發生硬解析,去找free chunk
雖然還有200M的free,
但所有chunk都不夠大,
這時候sql語句硬解析就會失敗。
失敗以後就會報一個很經典的oracle錯誤  
叫ora-4031錯誤

4031錯誤的產生原因是
1、大量的硬解析
2、大量的硬解析產生大量的小碎片以後突然又來了一些比較長的sql語句,
這個大sql語句,突然需要個大空間,
這時候沒有塊能提供這麼大的空間,就容易產生4031錯誤。

三)鏈

oracle裏面有很重要的一個概念chain即鏈
鏈有幾個特點,
1、它把我們需要組織的內存塊串起來,
它們功能或者說特性類似
2、鏈可以遍歷
因爲鏈有頭有尾,
所有的內存塊都是掛到鏈上,
我們可以找到第一個塊看看,再找第二個塊看看,可以從頭開始找到尾
就是可以遍歷並在鏈上找到所有的塊

oracle數據庫內存結構裏面
一個重要的特徵就是使用了大量的鏈
並且在使用時用鎖latch來保護鏈


四)librarycache裏存塊的組織

librarycache裏面也是用鏈來組織和管理chunk
鏈底下掛着chunk
這些chunk和free的chunk不一樣
它不是空的,裏面寫有內容,內容是sql語句和執行計劃plan
並且不是以大小來串起來的
而是以chunk所對應的sql語句運算以後得到的數字
掛到相應的鏈上
不管如何都是爲了方便我們查找和管理

塊在向鏈上掛時
首先把sql語句所有的字母轉換成ASCII碼值,
然後對這一堆數字進行一些運算,得到一個數字
這個數字就對應於鏈的編號。

如得到一個數字5,
我們就把這個sql語句及執行計劃掛到5號鏈上。

再次執行這條sql語句時
oracle同樣對這條sql語句求ASCII碼值
並進行一些運算得到鏈的編號5
5號鏈掛了好多chunk,oracle就會鎖住這個鏈
在鏈上進行遍歷
最後會找到了這個chunk
就不會發生硬解析了,發生的是軟解析

rowcache裏面也是以鏈的方式來組織管理的
 
內存塊存儲有鏈,有鏈就有鎖latch,
前面內容對應有
sharedpool latch,librarycache latch、rowcache latch

五)監視內存塊變化

1)庫中有一個視圖 x$ksmsp,我們叫x表
sharedpool裏面的每一個chunk,在這個表裏面都有一行信息。
select count(*) from x$ksmsp;
得到的數字就是sharedpool裏面的chunk總數。

執行這條語句
SQL> select count(*) from x$ksmsp;

  COUNT(*)
----------
     11648

數據庫系統目前有11648個chunk

再執行一條以前從來沒有執行過的語句
用來發生硬解析,它會從free上摘下chunk來放到librarycache上
SQL> select count(*) from dba_indexes;

  COUNT(*)
----------
      2344
語句執行後很有可能產生了碎片。

再看一下chunk數
SQL> select count(*) from x$ksmsp;

  COUNT(*)
----------
     11676
由11648變爲了11676
說明有硬解析發生,因爲chunk的數量增加了

將查詢x$ksmsp表的語句連續執行
比如十分鐘以內執行一次過十分鐘再執行一次
得到的兩個數字一減
我們可以算出在十分鐘以內產生的chunk的數量。

正常情況下隨着系統越來越穩定,產生的chunk的數量越來越少,
如果你發現十分鐘以內產生了大量的chunk,
很可能這時候系統裏面產生了大量的硬解析。

這是一個小技巧,
但是我們一般不用它來判斷軟硬解析的數量。

2)我們都用前面使用過的一條語句

SQL> select name,value from v$sysstat where name like 'parse%';

NAME                                                                  VALUE
---------------------------------------------------------------- ----------
parse time cpu                                                           53
parse time elapsed                                                      613
parse count (total)                                                    4255
parse count (hard)                                                      888
parse count (failures)                                                    0

直接看
parse count (hard)的值的變化,
就可以知道當前數據庫系統自啓動以來已經發生了多少硬解析
用它來判斷一個時間段發生的硬解析的數量,更好一些。

3)再看一下
alter system flush shared_pool;
這個命令很危險,不能任意執行,但偶爾也可以執行

我們叫它flush命令
它會將librarycache和rowcache所有的內容全部清空
並重置和重新初始化free中的所有塊和鏈。
這時候再去執行任何sql語句的時候都會發生硬解析,
所以這條語句我們輕易不要去執行

但是它執行完了以後4031錯誤馬上就會減少
因爲它一旦執行以後librarycache被清空
chunk會全部回到free裏面去
這時free裏會有大量的大大小小的chunk
這時候4031錯誤就不容易再出現了。

但這個命令執行完了以後,意味着接下來會產生大量的硬解析。
這個命令不是解決4031錯誤根本的辦法
它是治標不治本的一個命令。


這節課講了sharedpool裏面的內存結構,
什麼叫chain 什麼叫 chunk,
以及講了一個flush命令。
同時我們也知道,
硬解析大量存在的時候,會產生ora-4031錯誤。

我們怎麼去減少硬解析呢,
系統有沒有條件減少硬解析,
有沒有這種可能,
放到下一章節去講!


 2016年8月5日
                                                                            文字:韻箏

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章