Cache和Buffer是兩個不同的概念,簡單的說,Cache是加速“讀”,而 buffer是緩沖“寫”,前者解決讀的問題,保存從磁盤上讀出的數據,后者是解決寫的問題,保存即將要寫入到磁盤上的數據。在很多情況下,這兩個名詞並沒有嚴格區分,常常把讀寫混合類型稱為buffer cache,在Oracle Instance里同樣有一塊區域作為數據庫緩沖區&&高速緩存。
Oracle Overview
MySQL Memory Overview
數據庫設計普遍都會有插入緩沖、雙寫(double wirte)的特性,這些特性為數據庫帶來了更好的性能和更高的可靠性能。
雙寫
Oracle中的redo log buffer和MySQL Innodb引擎中的日志緩沖是解決redo寫入的問題,而database buffer cache和插入緩沖則解決data block的讀寫問題。
對於Oracle來說,如果IO沒有在SGA中命中,都會發生物理IO,Oracle並不關心底層存儲的類型,可能是一套存儲系 統,可能是本地磁盤,可能是RAID 10,也可能是RAID 5,可能是文件系統,也可能是裸設備,或是ASM。總之,Oracle把底層的存儲系統稱為存儲子系統。
存儲系統
在存儲系統中,buffer幾乎無處不在,文件系統有buffer,存儲有buffer,RAID控制器上有 buffer,磁盤上也有buffer。為了提高性能,Oracle的一個寫操作,很有可能寫在存儲的buffer上就返回了,如果這時存儲系統發生問題,Oracle如何來保證數據一致性的問題。
Oracle數據庫最重要的特性是:Write ahead logging,在data block在寫入前,必須保證首先寫入redo log,在事務commit時,同時必須保證redo log被寫入。Oracle為了保證數據的一致性,對於redo log采用了direct IO,Direct IO會跳過了OS上文件系統的cache這一層。但是,OS管不了存儲這一層,雖然跳過了文件系統的cache,但是依然可能寫在存儲的cache上。
對於MySQL來說,redolog在每次事務commit的時候,就立刻將事務更改操作記錄到redolog。所以即使bufferpool中的dirtypage在斷電時丟失,InnoDB在啟動時,仍然會根據redolog中的記錄完成數據恢復。redolog的另一個作用是,通過延遲dirtypage的flush最小化磁盤的隨機寫入。(redolog會合並一段時間內TRX對某個page的修改)
一般的存儲都有buffer,為了提高性能,寫操作在buffer上完成就返回給OS了,我們稱這種寫操作為write back,為了保證掉電時cache中的內容不會丟失,存儲都有電池保護,這些電池可以供存儲在掉電后工作一定時間,保證cache中的數據被刷入磁盤, 不會丟失。不同於UPS,電池能夠支撐的時間很短,一般都在30分鍾以內,只要保證buffer中的數據被寫入就可以了。存儲可以關閉寫cache,這時所 有的寫操作必須寫入到磁盤才返回,我們稱這種寫操作為write throuogh,當存儲發現某些部件不正常時,存儲會自動關閉寫buffer,這時寫性能會下降。
RAID
RAID卡上也有buffer,一般是256M,同樣是通過電池來保護的,不同於存儲的是,這個電池並不保證數據可以被寫入到磁盤上,而是為 buffer供電以保護數據不丟失,一般可以支撐幾天的時間。還有些RAID卡上有flash buffer,掉電后可以將cache中的內容寫入到flash buffer中,保證數據不丟失。如果你的數據庫沒有存儲,而是放在普通PC機的本地硬盤之上的,一定要確認主機中的RAID卡是否有電池,很多硬件提供商 默認是不配置電池的。當然,RAID卡上的buffer同樣可以選擇關閉。
磁盤
磁盤上的buffer,一般是16M-64M,很多存儲廠商都明確表示,存儲中磁盤的buffer是禁用的,這也是可以理解的,為了保證數據可靠性,而 存儲本身又提供了非常大的buffer,相比較而言,磁盤上的buffer就不再那么重要。SCSI指令中有一個FUA(Force Unit Access)的參數,設置這個參數時,寫操作必須在磁盤上完成才可以返回,相當於禁用了磁盤的寫buffer。雖然沒有查證到資料,但是我個人認為一旦磁 盤被接入到RAID控制器中,寫buffer就會被禁用,這也是為了數據可靠性的考慮,我相信存儲廠商應該會考慮這個問題。
至此,我們可以看到Oracle的一個物理IO是經歷了一系列的buffer之后,最終被寫入到磁盤上。buffer雖然可以提高性能,但是也要考慮掉電保護的問題。關於數據的一致性,是由Oracle數據庫,操作系統和存儲子系統共同來保證的。
插入緩沖
插入緩沖是InnoDB存儲引擎的關鍵特性。它並不僅僅是緩沖池的一部分,InnoDB緩沖池中有Insert Buffer信息固然不錯,但是Insert Buffer和數據頁一樣,也是物理頁的一個組成部分。
mysql> create table t ( id int auto_increment, name varchar(30), primary key (id), key(name) );


- redolog是一個環(ring)結構,當redo空間占滿時,將會將部分dirtypageflush到disk上,然后釋放部分redolog。這種情況可以通過Innodb_log_wait(SHOWGLOBALSTATUS)觀察,情況發生該計數器會自增一次。
- 當需要在Bufferpool分配一個page,但是已經滿了,並且所有的page都是dirty的(否則可以釋放不dirty的page),通常是不會發生的。這時候必須flushdirtypagestodisk。這種情況將會記錄到Innodb_buffer_pool_wait_free中。一般地,可以可以通過啟動參數innodb_max_dirty_pages_pct控制這種情況,當bufferpool中的dirtypage到達這個比例的時候,將會強制設定一個checkpoint,並把dirtypageflush到disk中。
- 檢測到系統空閑的時候,會flush,每次64pages。
淺談數據庫系統中的cache