天天看點

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日

                                                                            文字:韻筝