1. 程式人生 > >oracle學習筆記 buffer_cache大小的設定及依據

oracle學習筆記 buffer_cache大小的設定及依據



oracle學習筆記  buffer_cache大小的設定及依據


一)先回顧一下


前面講的buffercache的工作過程和大體的結構原理

磁碟有一堆dbf檔案
記憶體有buffercache

第一步:一個sql語句進來以後
如:select * from t2 where id=1;
首先是serverprocess會拿著這個sql語句去解析
解析的時候會用到cpu資源還會訪問rowcache
解析完成以後生成執行計劃再儲存到librarycache裡面去
這時sql語句的第一步解析執行完了

第二步:要執行語句
執行時要訪問資料

buffercache結構中一部分為鏈區,剩下的為buffer 
這裡面的鏈單元有地址指向裡面的一些buffer

這時oracle首先通過一系列的判斷以後
發現要訪問的表t2裡面id等於1的行
先判斷應該在哪個鏈上
它計算完了以後它發現這個行所在的塊應該在某個鏈上但不見得在這個鏈上
然後對這個鏈進行遍歷
第一種結果
在這個鏈上找到了這個block對應的buffer
既然找到了
這時候這個serverprocess直接讀這個buffer
不需要到磁碟再去讀了
第二種情況
在這個鏈上沒有找到這個block對應的buffer
這時serverprocess就會在buffer裡面找到一個可用的塊
假設一個塊可用
serverprocess把這個block讀到可用的buffer塊裡面去
同時把可用buffer塊的相關地址寫到對應鏈單元內
然後把資料接著讀出來

整個的,從鏈上找buffer,找不到時把block讀到記憶體去寫到buffer裡面去,然後再讀buffer
整個過程都是serverprocess做的

再看另外一個語句
update t2 set name=某個值 where id=1;
要修改某個block的某一行
這時同樣serverprocess經過解析以後要執行
執行時同樣判斷
這行所在的塊所在的block應該掛在某個鏈上
這裡在鏈上遍歷發現遍歷以後確實找到對應的buffer
直接在記憶體裡面修改buffer不須到磁碟上修改
修改完成以後buffer和block就不一致了
這個buffer就成了一個髒的buffer
這個buffer會被掛在LRUW上和CHECKPOINT佇列上

而前面select語句結果訪問的塊是乾淨的是可用的
它掛在LRU上

剛才最基本的知識都需要掌握
這是我們回顧的內容


二)DBWn程序和buffercache

接下來我們關心很多內容
某個髒塊髒了serverprocess並沒有把它寫回到磁碟上
是一個程序DBWn負責寫的,它是系統的一個程序

使用
[[email protected] ~]$ ps -ef|grep ora
查詢當前系統程序中與ora相關的程序

結果中有
oracle    3161     1  0 03:48 ?        00:00:00 ora_dbw0_jiagulun
的一個程序
此程序會把我們的髒塊寫到磁碟上

dbwn是一個後臺程序
serverprocess是一個前臺程序

我們的使用者送出一個sql語句
serverprocess接到sql語句
整個的從解析到執行到獲取這個過程都是serverprocess工作

serverprocess工作時使用者一直在等著,工作完了把結果返給使用者
使用者所執行的sql語句所等待的時間就是serverprocess工作的時間
所以serverprocess是直接面向用戶的叫前臺程序
我們希望它越快越好
我們就希望serverprocess所做的事情越少越好
將髒塊寫回磁碟我們沒有讓serverprocess去做
而是交給一個後臺程序DBWn這個程序
它的執行和使用者沒有關係,它並不影響使用者
它執行時使用者沒有在等待
它在後臺週期性執行

1)髒塊和DBWn的觸發


有很多條件會觸發DBWn
1、每隔一段時間DBWn會觸發
一般觸發不會將整個的所有的髒塊全寫回磁碟
它會找LRUW鏈
將冷端的幾個髒塊寫回磁碟
因為冷端意味著不怎麼經常被使用
這是第一個每隔一個時間段
每次寫的時候寫一批不是寫所有的
2、沒有了乾淨塊
對於乾淨的和free的塊我們可以覆蓋可以來使用
現在有一個block要調到記憶體裡面去
找了半天沒有找到乾淨塊沒有找到可用塊
這時也會觸發DBWn
DBWn會批量的寫一批buffer到磁碟上
寫過來的buffer和磁碟的block就一致了
一致以後就可用,這也是一種條件
3、資料庫關閉以後
DBWn會把所有的buffer全部寫回磁碟
1和2兩種情況最多

資料庫正常執行期間
1週期性DBWn觸發
2當我們的髒緩衝區到一定程度的時候會觸發DBWn
還有一種情況
我要在buffer裡面找一個可用塊的時候
半天都沒找著
就是找可用塊找的時間太長
雖然鏈還有剩餘,很多剩餘塊還沒有搜尋也會中途退出尋找
這裡有一個時間的閾值我們叫閥值也可以叫閾值
它也會觸發DBWn

總之DBWn是保證我們的髒塊能夠相對及時的合理的寫回到磁碟上

DBWn是後臺
它的工作不影響前臺不影響serverprocess
它在後臺默默的工作
我們用資料庫的時候並不怎麼關心DBWn

2)DBWn的個數

系統程序查詢時
結果有程序名為ora_dbw0_jiagulun
其中dbw0有個數字0
既然有0,就可以有1
也就是DBWn程序可以是多個
但是我們不要去設定過多的DBWn

我們可以看一個引數
SQL> show parameter writer

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
db_writer_processes                  integer     1
db_writer_processes引數目前的值是1
也就是隻有一個程序
一般的它的預設值DBWn的個數是cpu數量除上8
如果你16顆cpu的話就應該是兩個DBWn程序

一般DBWn程序是夠的

老師有一次去使用者那裡
看到有一個很奇怪的現象
那麼多的DBWn而且DBWn佔用cpu很高
最後發現它改過這個引數
老師問:你為什麼要改它?
他說:我覺得多一些資料庫更快!
老師的忠告是:其實不見得!

改這個引數也很容易
SQL> alter system set db_writer_processes=2;
alter system set db_writer_processes=2
                 *
ERROR at line 1:
ORA-02095: specified initialization parameter cannot be modified

結果提示這個引數不能被修改意味著它是靜態引數要使用scope=spfile選項靜態改

SQL> alter system set db_writer_processes=2 scope=spfile;

System altered.


然後重啟資料庫

SQL> startup force;
ORACLE instance started.

Total System Global Area  285212672 bytes
Fixed Size                  1218968 bytes
Variable Size             104859240 bytes
Database Buffers          171966464 bytes
Redo Buffers                7168000 bytes
Database mounted.
Database opened.

測試環境下startup force可以重啟資料庫
但實際環境這樣重啟很危險的
因為這樣重啟
整個過程中的關閉資料庫過程會被強制執行
而不管有沒有正在執行的程序和正在連線的使用者
非常可能造成資料的丟失,和引起資料庫故障。

再去查一下
[[email protected] ~]$ ps -ef|grep ora
結果中
oracle   21914     1  0 09:09 ?        00:00:00 ora_dbw0_jiagulun
oracle   21916     1  0 09:09 ?        00:00:00 ora_dbw1_jiagulun
有這麼兩行

說明目前DBWn有兩個程序
ora_dbw0_jiagulun和ora_dbw1_jiagulun
因為我們把db_writer_processes引數值設成2了

這次教給大家DBWn程序的數量到底設幾個不要亂設


三)buffercache大小


buffercache很重要,目前為止到底該設多大呢

1)buffercache大小的查詢和修改

buffercache的設定和sharedpool的設定很相似
一種情況我們單獨的去設定
如buffercache設定1個g或2個g
另外可以把buffercache的設定放在SGA target裡面去
oracle自動去設定buffercache大小
在實際的生產中我們還是經常的去手工設buffercache大小

這句
SELECT component,current_size,min_size FROM v$sga_dynamic_components;
是查一下當前我們sga裡面的各個元件到底是多大

buffer設定大小
alter system set db_cache_size=20M scope=memory;
也可以scope=both
設定buffercache大小這裡設的是20M

一般的有一個原則
DB_CACHE_SIZE = SGA_MAX_SIZE/2~ SGA_MAX_SIZE*2/3
dbcache設的大小一般是
SGA_MAX_SIZE的二分之一到三分之二
也就是整個的SGA的一半到三分之二的空間
我們建議大家直接設成三分之二
當然這個值不是很準確
我們到時候去通過相關的命令去設定去查

先查一下sga的狀態
SQL> SELECT component,current_size,min_size FROM v$sga_dynamic_components;                                               
COMPONENT                                                        CURRENT_SIZE   MIN_SIZE
---------------------------------------------------------------- ------------ ----------
shared pool                                                         100663296   96468992
large pool                                                            4194304    4194304
java pool                                                             4194304    4194304
streams pool                                                                0          0
DEFAULT buffer cache                                                167772160  167772160
KEEP buffer cache                                                           0          0
RECYCLE buffer cache                                                        0          0
DEFAULT 2K buffer cache                                                     0          0
DEFAULT 4K buffer cache                                                     0          0
DEFAULT 8K buffer cache                                                     0          0
DEFAULT 16K buffer cache                                                    0          0
DEFAULT 32K buffer cache                                                    0          0
ASM Buffer Cache                                                            0          0

13 rows selected.

這一行
DEFAULT buffer cache                                                167772160  167772160
是buffercache的大小
目前是100多M
sga總體大小為200多M
buffercache佔了二分之一要多

仔細查一下設定的值
SQL> show parameter sga

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
lock_sga                             boolean     FALSE
pre_page_sga                         boolean     FALSE
sga_max_size                         big integer 272M
sga_target                           big integer 272M
sga設定的總大小sga_target為272M


SQL> show parameter db_cache_size

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
db_cache_size                        big integer 0
db_cache_size的設定的值為預設值0,說明沒有設定大小,用的全是由SGA自動調整

我們可以自己設定大小
我們設大小隻能往大了設,往小了設沒有意義
設的值比oracle系統分配給它的值小了
oracle不會理會這個自己設的值仍會採用自動分配的值

現在改一下
alter system set db_cache_size=200M scope=both;

SQL> alter system set db_cache_size=200M scope=both;
alter system set db_cache_size=200M scope=both
*
ERROR at line 1:
ORA-32017: failure in updating SPFILE
ORA-00384: Insufficient memory to grow cache
結果顯示沒有足夠的記憶體去增加

就是sga_target已經就這麼大了,都分完了
都分給各個池子了
這時要把DEFAULT buffer cache的值增加
要增加這個buffercache池子的大小的話
首先增加sga的大小

這地方首先說一下思路
首先增加sga_max_size大小
然後再增加sga_target
最後再增加db_cache_size

語句分別為

alter system set sga_max_size=500M scope=spfile;
alter system set sga_target=400M;
alter system set db_cache_size=200M;

其中的scope選項有三個可取值

scope=spfile
表示將引數值存入spfile檔案,即改變oracle的初始化引數檔案內容,在重啟資料庫後才能生效
scope=memory
表示改變正在記憶體中執行的例項的引數值,只在記憶體上修改,立即生效,
關閉例項此值就會丟失而被還原為原已儲存的值,因為這個修改並沒有寫入到初始化引數檔案
scope=both
表示將引數值同時存入spfile和memory,立即生效,因為存入了spfile重啟資料庫後仍然有效。

both是預設值,修改靜態引數必須使用spfile,動態引數三種方式都可以用。

spfile檔案的位置
SQL> show parameter spfile

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
spfile                               string      /u01/app/oracle/product/10.2.0
                                                 /db_1/dbs/spfilejiagulun.ora

為了保護資料庫的安全有的引數進行了保護把它指定為靜態狀態
修改值時要加額外引數並且要資料庫重啟才能生效
但大部分引數是動態的可以隨時修改隨時生效
sga_max_size是靜態引數,sga_target和db_cache_size是動態引數

這三個引數目前值
sga_max_size                         big integer 272M
sga_target                           big integer 272M
db_cache_size                        big integer 0
因為sga_max_size和sga_target當前值相同
所以這裡必須先修改sga_max_size並重啟資料庫後
才能繼續修改sga_target的值使其增加
在sga有足夠空間時才能增加db_cache_size的值

我的修改過程
在sga_target把值增加後就會立即自動把剩餘的空間全部分配給db_cache_size
以為是因為db_cache_size使用預設值0,
但手工對db_cache_size分配值後效果仍然一樣。

在修改db_cache_size的值時

增加時是有限制的
sga要根據當前所有的狀態值分析有沒有足夠的空間滿足這個增大的值

減少時一般沒限制
因為這個值即使設定小了但sga仍使用自動分配空間分配給db_cache_size
一般真實值不會減少,仍保持在合理狀態

2)buffercache的合理值

有一個命令
SELECT size_for_estimate "Cache Size (MB)",size_factor,buffers_for_estimate "Buffers",
estd_physical_read_factor est_read_factor,
estd_physical_reads estd_phy_red,estd_physical_read_time est_phy_red_t
FROM  v$db_cache_advice
WHERE NAME='DEFAULT' AND block_size=(SELECT VALUE FROM v$parameter WHERE NAME='db_block_size');
可以通過這個命令查一下當前資料庫buffercache該設多大

執行一下:
SQL> SELECT size_for_estimate "Cache Size (MB)",size_factor,buffers_for_estimate "Buffers",
estd_physical_read_factor est_read_factor,
  2  estd_physical_reads estd_phy_red,estd_physical_read_time est_phy_red_t
  3    4  FROM  v$db_cache_advice
WHERE NAME='DEFAULT' AND block_size=(SELECT VALUE FROM v$parameter WHERE NAME='db_block_size');  5

Cache Size (MB) SIZE_FACTOR    Buffers EST_READ_FACTOR ESTD_PHY_RED EST_PHY_RED_T
--------------- ----------- ---------- --------------- ------------ -------------
             16          .1       1996          1.7523        14677            77
             32          .2       3992          1.1516         9646            48
             48          .3       5988               1         8376            40
             64          .4       7984               1         8376            40
             80          .5       9980               1         8376            40
             96          .6      11976               1         8376            40
            112          .7      13972               1         8376            40
            128          .8      15968               1         8376            40
            144          .9      17964               1         8376            40
            160           1      19960               1         8376            40
            176         1.1      21956               1         8376            40
            192         1.2      23952               1         8376            40
            208         1.3      25948               1         8376            40
            224         1.4      27944               1         8376            40
            240         1.5      29940               1         8376            40
            256         1.6      31936               1         8376            40
            272         1.7      33932               1         8376            40
            288         1.8      35928               1         8376            40
            304         1.9      37924               1         8376            40
            320           2      39920               1         8376            40

20 rows selected.

我們看一下這些列
Cache Size (MB)是假設的大小
如第一行結果
             16          .1       1996          1.7523        14677            77
設16MB的話會有1996個buffer

當前資料庫設定的塊的大小
SQL> show parameter db_block_size

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
db_block_size                        integer     8192

所以一個buffer是8K

16MB除以8K就是第一行Buffers列的值

EST_READ_FACTOR 為預估的物理讀因子
ESTD_PHY_RED 預估的物理讀的次數
EST_PHY_RED_T 預估的物理讀時間

我們可以以物理讀時間作為標準
因為buffercache最最突出的作用是快取block
目的是減少物理io
這樣就減少了物理io讀的時間

如果設16M的話
預測的物理讀次數14677,系統的物理讀時間是77

如果設32M的話
預測的物理讀次數9646,物理讀時間是48

ESTD_PHY_RED和EST_PHY_RED_T基本上是同步的
次數多時間就長

對我們當前資料庫來講實際上
因為我的資料庫沒有任何負載48M就可以了
因為你設的再怎麼大
它對物理讀的次數和物理讀的時間的減少沒有任何意義

在實際生產中我們就是找這個數值
它對應的這行最後邊三列的值,在此行以後的行這三列的數值變化不大的時候
找此行Cache Size (MB)值設定就可以了

視訊課程中我們可以看到
老師個人比較喜歡
把平時要做的很多操作的一些sql語句提前給它找出來
找好了以後給它寫到txt檔案裡面去
以後幹活的時候在txt檔案中找直接複製出來用就行了
這樣它就成為了老師的一個工具
老師希望學生回去以後也要在這方面要去好好的去積累
積累以後你幹活的時候有工具
你幹活的時候就會非常的好
所以這些收集的語句都很重要

這個地方我們講了buffercache該設多大怎麼設
還教大家怎麼看當前大小
這是buffercache
知道這個以後基本的操作基本上都會了

這節課主要內容講了buffercache的設定
後面的課是block的狀態
block狀態其實應該是buffer的狀態
裡面好多東西可能大家不太理解需要詳細的講一下
內容還有一堆sql語句


2016年9月25日
     文字:韻箏