Shared pool内存块组成结构及4031错误原因分析
生活随笔
收集整理的這篇文章主要介紹了
Shared pool内存块组成结构及4031错误原因分析
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
這篇文章是參考甲骨論老相老師的教學視頻所做的學習筆記:
http://v.youku.com/v_show/id_XMzkyMDQ4MzUy.html
之前提到Shared pool的作用:
Shared pool是用來緩存sql語句以及sql的執行計劃的,
而share pool包含3主要大部分(還有其他很多部分)
分別是library cache, rowcache和 free memory
?
首先強調一句: 我們可以手動設置Shared pool的大小, 但是并不能制定shared pool里面 Free/Library Cache/rowcache 等各部分的大小的.
1.現在分析下Free 空間的內存空間:
其實可以參考下圖:
?
?
?????? 如上圖,? 其實Free空間并不是1個大的內存塊, 而是由許多個有固定順序內存鏈(chain)組成的,其中每1條chain都有起始位置和終點,在每1條chain上都掛著許多大小相近的內存塊(chunk).例如上面第一條chain掛著chunk大小大概是每個4k,中間是每個chunk 8k,最下面果條每個12k啦~
??????? 但是了解過數據結構的都知道, 內存鏈chain在物理上是不存在的, 而每個chunk也不是物理上相鄰的, 每1條鏈實際上是分別在內存里各個位置的若干個chunk組成. 第1個chunk的頭部放著這條chain的起始位置,也就是這條chain的內存位置,然后尾部放著1個指針,指向下1個chunk的內存地址..? 直到之后1個chunk尾部不放指針. 這樣就組成了1條內存鏈chunk
但是邏輯上可以參照上圖理解啦~
2. 現在要解析一條sql語句, 需要占用free空間.
?? 假如,現在要解析一條新的語句, 需要額外的10k空間,? 那么server process會怎么找出這10k的空間呢,
如下圖, 首先下圖中8k那第條鏈,它的chunk都是8k - 12k的, 所以server process會找這一條鏈遍歷,假如它找到一個chunk是11k了,那么它會將這個chunk分成10k 和 1k兩個部分,? 其中10k 那個部分作為1個新的chunk放到 屬于library cache的chain中, 就相當于把這個chunk從free空間移到 library cache了(當然不是物理上移動這個chunk,只需修改相應的chunk尾部指針).? 而剩余的1k那個部分,也不能留在8k這一條鏈了, 會比移到存放1k左右chunk的那條鏈.
??由這過程可以得出,這種sql語句解析動作很可能會產生一些小的內存碎片(1k那個部分), 實際上這種sql動作就是所謂的硬解析,而軟解析只需在library cache查找出緩存的執行計劃,是不需要去征用Free memory的.
關于硬解析和軟解析可以參考:http://nvd11.blog.163.com/blog/static/200018312201301682642475/
3. 4031錯誤的產生
????? 所以說硬解析會產生內存碎片, 而一個服務器在進行大量的硬解析是則在shared pool產生大量的碎片, 這時即使Free Memory空間內還有不少的空間, 但里面很可能都是小chunk(碎片), 而沒有大的chunk了.
?????? 這時,若數據庫又接受到1個很復雜的sql語句要進行硬解析, 需要在free空間找一些大的chunk,但是free空間內只有碎片..這樣這個硬解析會失敗,而oracle則可能會報1這種很經典的錯誤,就是4031錯誤.
所以4031錯誤的產生原因有兩個:
1. 數據庫大量的硬解析.
2. 大量硬解析產生大量的碎片,而這時又要執行1個復雜的硬解析動作.
4. 內存鏈(chain)的結構.
其實內存鏈的結構可以參考下圖啦:
?
上圖是由3個chunk組成的內存鏈 chain.
可以看出內存chain內的chunk在物理上并不一定是相鄰的,而且也不一定是在物理上按順序排列的.
如上圖, 物理上排中間那個chunk才是chain中的第一個chunk, 因為沒有指針指向它的頭部地址, 然后它的尾部指向第2個chain..
而第3個chain因為他的尾部是空指針,所以他是這個內存鏈的最后1個chunk.
所以當加入和刪除chunk時只需改變相應chunk的指針指向就可以了
其實這是1個經典的鏈表結構啦.
5. 內存鏈(chain)的一些特性
所以chain有兩個特點:
1. 由多個chunk串聯組成.
2. 可以遍歷(根據指針去遍歷啦)
而Oracle 會 讓一種叫Latch的鎖去保護chain的結構.
6. Server process會寫一些什么內容進入Chunk呢.
我們由上面的圖解可知. 那些chunk在free空間里面是空的, 搬到library cache里面會被寫上內容了.
下面就分析到底寫了什么數據進去..
我們知道library cache是用來存放sql語句和其執行計劃的, 那么里面數據肯定與之相關了:
首先
sql語句會被轉換成ASCII碼, 然后經過一系列若干步算法, 會轉會成一串數字:
而最終這串數子,包換1個鏈的編碼,加入這個號碼是5.
當然如果是硬解析,則server process還會解析這個sql,并得出執行計劃寫到這個chunk上.
如下圖
?
7. 軟解析和硬解析
???? 由上圖得知, 每一條sql語句總會經過運算得到1個chain號碼.
1.所以當某條sql語句進入shared pool時.??? 系統會首先計算出對應這個sql的chain號碼(上圖動作1)
2. 然后server process會在library cache對應號碼的chain上遍歷,尋找有無緩存了這條sql的執行計劃的chunk.
3. 如果找不到,則會在Free 空空間搬1個新的chunk掛到 library cache的對應chain上,別解析sql語句得出執行計劃寫入這個chunk中.這就是硬解析(上圖動作2)
4.這時這個session或另一個session 傳送來另1個相同的sql語句. 經過運算得出相同的chain號.(動作1)
5.server process還是會在對應chain上遍歷,因為之前硬解析過一次,所以這次找到緩存執行計劃的chunk了,就直接將該執行機會拿出來用了,這就是軟解析,不需執行動作2
8. library cache里面的chain管理.
?????????????? 由上面分析得知, library cache里與free空間不同,并不是按chunk的大小空間去組成1條chain的,而是按硬解析后sql的運算出來的chain號碼來組成1條chain的. 這樣更加方便server process去查找緩存
????????????? 跟free空間一樣, library cache同樣有 Library cache latch去維護chain的結構.
9. Rowcache(字典緩存)以用樣類似的方式去管理
也是說同樣是chain結構. 而且居然rowcache latch了
10. 一些動態數據字典:
10.1 x$ksmsp 這張表 存放了shared pool的每1個chunk的信息.
x$ksmsp的detail信息可以參考這里.
執行select count(1) from x$ksmsp 能查看shared pool chunk總數
這時我們執行一條之前從未執行過的sql語句(會發生硬解析)
這時,再去查看shared pool的chunk數量,發現增加了,也代表硬解析產生了碎片..
也可以理解出, shared pool里面的chunk數量越多(大小固定之下), 碎片就越嚴重.
加入我們每10分鐘執行一次查詢, 那么10分鐘后的chunk數量 - 10分鐘前的chunk數量就是這10分鐘增加的chunk數量
隨著系統運行,應該沒10分鐘增加的chunk數量應該會越來越少(緩存數據增多,軟解析多).
若某一段時間增加了大量chunk數量,通常代表這段時間發生大量的硬解析.產生了大量碎片.
不過通常我們會利用 v$sysstat 來查看硬解析數量.
?11, 清空shared pool緩存數據.
Alter system flush shared pool;
這條命令用于清空shared pool所有的緩存數據!
通常執行這條命令后, 4031錯誤就會消失, 但是接下來就會發生大量硬解析,因為緩存都被清空啦.
所以對于4031錯誤來講,執行這條命令只是1個治標不治本的方法...? 治本方法通常是加大shared pool的大小,也就是加內存啦.
?
http://v.youku.com/v_show/id_XMzkyMDQ4MzUy.html
之前提到Shared pool的作用:
Shared pool是用來緩存sql語句以及sql的執行計劃的,
而share pool包含3主要大部分(還有其他很多部分)
分別是library cache, rowcache和 free memory
?
首先強調一句: 我們可以手動設置Shared pool的大小, 但是并不能制定shared pool里面 Free/Library Cache/rowcache 等各部分的大小的.
1.現在分析下Free 空間的內存空間:
其實可以參考下圖:
?
?
?????? 如上圖,? 其實Free空間并不是1個大的內存塊, 而是由許多個有固定順序內存鏈(chain)組成的,其中每1條chain都有起始位置和終點,在每1條chain上都掛著許多大小相近的內存塊(chunk).例如上面第一條chain掛著chunk大小大概是每個4k,中間是每個chunk 8k,最下面果條每個12k啦~
??????? 但是了解過數據結構的都知道, 內存鏈chain在物理上是不存在的, 而每個chunk也不是物理上相鄰的, 每1條鏈實際上是分別在內存里各個位置的若干個chunk組成. 第1個chunk的頭部放著這條chain的起始位置,也就是這條chain的內存位置,然后尾部放著1個指針,指向下1個chunk的內存地址..? 直到之后1個chunk尾部不放指針. 這樣就組成了1條內存鏈chunk
但是邏輯上可以參照上圖理解啦~
2. 現在要解析一條sql語句, 需要占用free空間.
?? 假如,現在要解析一條新的語句, 需要額外的10k空間,? 那么server process會怎么找出這10k的空間呢,
如下圖, 首先下圖中8k那第條鏈,它的chunk都是8k - 12k的, 所以server process會找這一條鏈遍歷,假如它找到一個chunk是11k了,那么它會將這個chunk分成10k 和 1k兩個部分,? 其中10k 那個部分作為1個新的chunk放到 屬于library cache的chain中, 就相當于把這個chunk從free空間移到 library cache了(當然不是物理上移動這個chunk,只需修改相應的chunk尾部指針).? 而剩余的1k那個部分,也不能留在8k這一條鏈了, 會比移到存放1k左右chunk的那條鏈.
??由這過程可以得出,這種sql語句解析動作很可能會產生一些小的內存碎片(1k那個部分), 實際上這種sql動作就是所謂的硬解析,而軟解析只需在library cache查找出緩存的執行計劃,是不需要去征用Free memory的.
關于硬解析和軟解析可以參考:http://nvd11.blog.163.com/blog/static/200018312201301682642475/
3. 4031錯誤的產生
????? 所以說硬解析會產生內存碎片, 而一個服務器在進行大量的硬解析是則在shared pool產生大量的碎片, 這時即使Free Memory空間內還有不少的空間, 但里面很可能都是小chunk(碎片), 而沒有大的chunk了.
?????? 這時,若數據庫又接受到1個很復雜的sql語句要進行硬解析, 需要在free空間找一些大的chunk,但是free空間內只有碎片..這樣這個硬解析會失敗,而oracle則可能會報1這種很經典的錯誤,就是4031錯誤.
所以4031錯誤的產生原因有兩個:
1. 數據庫大量的硬解析.
2. 大量硬解析產生大量的碎片,而這時又要執行1個復雜的硬解析動作.
4. 內存鏈(chain)的結構.
其實內存鏈的結構可以參考下圖啦:
?
上圖是由3個chunk組成的內存鏈 chain.
可以看出內存chain內的chunk在物理上并不一定是相鄰的,而且也不一定是在物理上按順序排列的.
如上圖, 物理上排中間那個chunk才是chain中的第一個chunk, 因為沒有指針指向它的頭部地址, 然后它的尾部指向第2個chain..
而第3個chain因為他的尾部是空指針,所以他是這個內存鏈的最后1個chunk.
所以當加入和刪除chunk時只需改變相應chunk的指針指向就可以了
其實這是1個經典的鏈表結構啦.
5. 內存鏈(chain)的一些特性
所以chain有兩個特點:
1. 由多個chunk串聯組成.
2. 可以遍歷(根據指針去遍歷啦)
而Oracle 會 讓一種叫Latch的鎖去保護chain的結構.
6. Server process會寫一些什么內容進入Chunk呢.
我們由上面的圖解可知. 那些chunk在free空間里面是空的, 搬到library cache里面會被寫上內容了.
下面就分析到底寫了什么數據進去..
我們知道library cache是用來存放sql語句和其執行計劃的, 那么里面數據肯定與之相關了:
首先
sql語句會被轉換成ASCII碼, 然后經過一系列若干步算法, 會轉會成一串數字:
而最終這串數子,包換1個鏈的編碼,加入這個號碼是5.
當然如果是硬解析,則server process還會解析這個sql,并得出執行計劃寫到這個chunk上.
如下圖
?
7. 軟解析和硬解析
???? 由上圖得知, 每一條sql語句總會經過運算得到1個chain號碼.
1.所以當某條sql語句進入shared pool時.??? 系統會首先計算出對應這個sql的chain號碼(上圖動作1)
2. 然后server process會在library cache對應號碼的chain上遍歷,尋找有無緩存了這條sql的執行計劃的chunk.
3. 如果找不到,則會在Free 空空間搬1個新的chunk掛到 library cache的對應chain上,別解析sql語句得出執行計劃寫入這個chunk中.這就是硬解析(上圖動作2)
4.這時這個session或另一個session 傳送來另1個相同的sql語句. 經過運算得出相同的chain號.(動作1)
5.server process還是會在對應chain上遍歷,因為之前硬解析過一次,所以這次找到緩存執行計劃的chunk了,就直接將該執行機會拿出來用了,這就是軟解析,不需執行動作2
8. library cache里面的chain管理.
?????????????? 由上面分析得知, library cache里與free空間不同,并不是按chunk的大小空間去組成1條chain的,而是按硬解析后sql的運算出來的chain號碼來組成1條chain的. 這樣更加方便server process去查找緩存
????????????? 跟free空間一樣, library cache同樣有 Library cache latch去維護chain的結構.
9. Rowcache(字典緩存)以用樣類似的方式去管理
也是說同樣是chain結構. 而且居然rowcache latch了
10. 一些動態數據字典:
10.1 x$ksmsp 這張表 存放了shared pool的每1個chunk的信息.
x$ksmsp的detail信息可以參考這里.
執行select count(1) from x$ksmsp 能查看shared pool chunk總數
這時我們執行一條之前從未執行過的sql語句(會發生硬解析)
這時,再去查看shared pool的chunk數量,發現增加了,也代表硬解析產生了碎片..
也可以理解出, shared pool里面的chunk數量越多(大小固定之下), 碎片就越嚴重.
加入我們每10分鐘執行一次查詢, 那么10分鐘后的chunk數量 - 10分鐘前的chunk數量就是這10分鐘增加的chunk數量
隨著系統運行,應該沒10分鐘增加的chunk數量應該會越來越少(緩存數據增多,軟解析多).
若某一段時間增加了大量chunk數量,通常代表這段時間發生大量的硬解析.產生了大量碎片.
不過通常我們會利用 v$sysstat 來查看硬解析數量.
?11, 清空shared pool緩存數據.
Alter system flush shared pool;
這條命令用于清空shared pool所有的緩存數據!
通常執行這條命令后, 4031錯誤就會消失, 但是接下來就會發生大量硬解析,因為緩存都被清空啦.
所以對于4031錯誤來講,執行這條命令只是1個治標不治本的方法...? 治本方法通常是加大shared pool的大小,也就是加內存啦.
?
總結
以上是生活随笔為你收集整理的Shared pool内存块组成结构及4031错误原因分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Oracle 杀死session的方法
- 下一篇: 共享SQL语句减少硬解析