?
? ????? PHP ??? ???? ??? ?? ??
可靠性是任何嚴(yán)肅的數(shù)據(jù)庫系統(tǒng)的重要屬性,PostgreSQL 盡一切可能來保證可靠的操作??煽啃圆僮鞯囊粋€(gè)方面是所有已提交 的數(shù)據(jù)都應(yīng)該存儲(chǔ)在一個(gè)非易失的區(qū)域,這樣就不會(huì)因?yàn)殡娏κА? 操作系統(tǒng)崩潰、硬件失效(除了非易失區(qū)域自身失效之外)等原因?qū)е聰?shù)據(jù)丟失。 向計(jì)算機(jī)的永久存儲(chǔ)(磁盤驅(qū)動(dòng)器或者等效的東西)成功寫入數(shù)據(jù)通??梢詽M足這個(gè)要求。 實(shí)際上,即使計(jì)算機(jī)完全失效,只要磁盤驅(qū)動(dòng)器生存下來,那么它們就可以移動(dòng)到另外一 臺(tái)類似硬件的計(jì)算機(jī)上,而所有已經(jīng)提交的事務(wù)將保持原狀。
周期性地強(qiáng)制數(shù)據(jù)寫入磁盤盤片看上去像一件簡單的操作, 但實(shí)際上不是。因?yàn)榇疟P驅(qū)動(dòng)器比內(nèi)存和 CPU 要慢許多, 在計(jì)算機(jī)的主存和磁盤盤片之間存在多層緩沖。 首先, 有操作系統(tǒng)的緩沖區(qū)內(nèi)存,它緩沖常用的磁盤塊并且組合 對(duì)磁盤寫入的請(qǐng)求。幸運(yùn)的是,所有操作系統(tǒng)都給予應(yīng)用一個(gè) 強(qiáng)制從緩沖區(qū)寫入磁盤的方法,PostgreSQL 使用了該特性(參閱wal_sync_method 參數(shù))。
然后,在磁盤驅(qū)動(dòng)器的控制器上可能還有一個(gè)緩沖; 特別是在RAID控制卡上更為常見。 這些緩沖區(qū)中,有些是透過式寫入,意思是寫入動(dòng)作 在到達(dá)的同時(shí)寫入到磁盤上。其它則是回寫式寫入, 意思是數(shù)據(jù)將在稍后寫入驅(qū)動(dòng)器。這樣的緩沖區(qū)是可靠性的危害, 因?yàn)榇疟P控制器上的內(nèi)存是易失的,在發(fā)生電力失效的情況下會(huì)丟失其中的內(nèi)容。 好一些的控制器卡備有電池供電的緩沖區(qū)( BBU的 S),這意味著該卡具有的電池 可以在系統(tǒng)電力失效的情況下提供電力。在電力恢復(fù)之后,這些數(shù)據(jù)將會(huì)被寫入磁盤驅(qū)動(dòng)器。
最后,大多數(shù)磁盤驅(qū)動(dòng)器自身也有緩沖區(qū)。有些是透過式的, 有些是回寫式的,和磁盤控制器一樣,回寫式的磁盤緩沖區(qū)也存在數(shù)據(jù)丟失的問題。 消費(fèi)級(jí)別的IDE和SATA驅(qū)動(dòng)器特別容易包含回寫式緩沖,在掉電的情況下很容易丟失數(shù)據(jù)。 大多固態(tài)硬盤(SSD)同樣有回寫緩沖區(qū)。
這些緩沖區(qū)通常是不可用的;但這種方法隨著操作系統(tǒng)和驅(qū)動(dòng)類型的改變:
在Linux上,IDE驅(qū)動(dòng)可以通過使用hdparm -I來查詢; 如果在Write cache后接著一個(gè)*是不可以寫緩沖。 hdparm -W能夠用來關(guān)閉謝緩沖。請(qǐng)?jiān)?span id="377j5v51b" class="APPLICATION">sdparm內(nèi)查詢SCSI驅(qū)動(dòng)。 使用sdparm --get=WCE檢測寫緩沖是否關(guān)閉并且可以使用sdparm --clear=WCE關(guān)閉它。
在FreeBSD上,IDE驅(qū)動(dòng)可以使用atacontrol 來查詢,并且SCSI驅(qū)動(dòng)可以使用sdparm。
在Solaris上,磁盤寫緩存是受format -e 控制的。(Solaris ZFS文件系統(tǒng)是受寫緩沖保護(hù)的,應(yīng)為它發(fā)行自己的磁盤緩存刷新命令。)
在Windows上,如果wal_sync_method是open_datasync(缺省時(shí)), 對(duì)My Computer\Open\disk drive\Properties\Hardware\Properties\Policies\Enable write caching on the disk 取消選擇就可以禁止寫緩存。另外,禁止寫緩存可以設(shè)置wal_sync_method為fsync或fsync_writethrough。
在Mac OS X里,能夠通過wal_sync_method對(duì)fsync_writethrough設(shè)置 以阻止寫緩沖。
最新的SATA驅(qū)動(dòng)(在ATAPI-6或更高版本后)提供一個(gè)引導(dǎo)緩存刷新的命令(FLUSH CACHE EXT), 而SCSI驅(qū)動(dòng)長期以來提供一個(gè)更簡短的命令:SYNCHRONIZE CACHE。 這些命令不能直接作用在PostgreSQL上,但是一些文件系統(tǒng)(例如, ZFS, ext4) 通過回寫功能的驅(qū)動(dòng)能夠使用命令在磁盤上對(duì)數(shù)據(jù)刷新。但是,當(dāng)綁定電池備份單元磁盤控制器時(shí), 文件系統(tǒng)表現(xiàn)的性能不理想。在這樣的設(shè)置下,同步命令強(qiáng)制控制器緩存內(nèi)的所有數(shù)據(jù) 寫進(jìn)磁盤中,會(huì)掩蓋BBU的大部分的優(yōu)點(diǎn)。你可以運(yùn)行在PostgreSQL的資源樹的功能src/tools/fsync 來查看是否受到影響。如果受到影響,并且在文件系統(tǒng)或磁盤控制器重新配置的關(guān)閉可選的話, BBU的性能優(yōu)勢能夠恢復(fù)。如果寫入阻礙關(guān)閉了,確保電池的長期平穩(wěn)運(yùn)行, ,否則一股損壞的電池會(huì)導(dǎo)致數(shù)據(jù)的丟失。
在操作系統(tǒng)向磁盤硬件發(fā)出一個(gè)寫請(qǐng)求的時(shí)候,它沒有什么好辦法來保證數(shù)據(jù) 真正到達(dá)非易失的存儲(chǔ)區(qū)域。實(shí)際上,確保所有存儲(chǔ)部件都保證數(shù)據(jù)的完整性是管理員的責(zé)任。 應(yīng)該避免使用沒有電池供電的回寫緩沖磁盤控制器。在磁盤級(jí)別, 如果驅(qū)動(dòng)器不能保證在關(guān)閉(掉電)之前寫入數(shù)據(jù),那么應(yīng)該關(guān)閉回寫緩沖。 diskchecker.pl. 如果你使用的是固態(tài)硬盤要注意在默認(rèn)情況下,很多情況是不會(huì)按照緩沖刷新命令執(zhí)行的。 你可以利用diskchecker.pl對(duì)子系統(tǒng)的穩(wěn)定I/O嘗試下。
另外一個(gè)數(shù)據(jù)丟失的風(fēng)險(xiǎn)來自磁盤盤片寫操作自身。磁盤盤片會(huì)被分割為段, 通常每段 512 字節(jié)。每次物理讀寫都對(duì)整個(gè)段進(jìn)行操作。當(dāng)一個(gè)寫操作到達(dá)磁盤的時(shí)候, 它可能是512字節(jié)、1024字節(jié)、或者8192字節(jié)(在一段時(shí)間的PostgreSQL通常寫入8192字節(jié),或 16個(gè)部門),而寫入操作可能因?yàn)殡娏κФS時(shí)失敗,意味著某些 512 字節(jié)的段寫入了, 而另一些則沒有。為了避免這個(gè)問題,PostgreSQL在修改磁盤上的實(shí)際 頁面之前周期性地把整個(gè)頁面的影像寫入永久存儲(chǔ)。這樣,在崩潰恢復(fù)的時(shí)候, PostgreSQL就可以從WALL恢復(fù)部分寫入的頁面。 如果你有一個(gè)電池供電的磁盤控制器或者是文件系統(tǒng)(比如ZFS)自身能夠避免部分頁面寫入, 你可以通過full_page_writes參數(shù)來關(guān)閉頁面影像功能。 電池備份單元(BBU)磁盤控制器不會(huì)阻止部分頁面寫入,除非 他們保證,數(shù)據(jù)被寫入全頁(8KB)的BBU。