標籤:
2.3 理解一致性和資料丟失
挖掘PostgreSQL交易記錄而不考慮一致性是不可能的。在本章的第一部分,我們已經大體上解釋了交易記錄的基本思想。您已經知道,無需事先的日誌改變的能力,使資料處於一種好的形狀是很難甚至是不可能的。
到現在為止,我們大多都在討論崩潰的問題。因為資料檔案中的條目的損壞而丟失檔案是絕對不好的。但是,崩潰不是您要關心的唯一問題。另外兩個重要的主題是:
• 效能
• 資料丟失
雖然這可能是一個重要的主題的明顯的選擇,我們有這樣的感覺,這兩個主題都不好理解,是受尊敬的,並因此需要考慮。
在我們的日常業務為PostgreSQL諮詢專家和培訓師,我們通常會看到那些只專註於效能的人。
Performance is everything, we want to be fast; tell us how to be fast…
潛在的資料丟失,或者甚至是一個來處理它的概念的意識。對許多人來說,這看起來是新東西。我們這樣看:如果資料丟失甚至更快有什麼好處呢?這樣做的關鍵不是效能不重要;效能是非常重要的。然而,我們只是想指出效能不是全域中唯一的組成部分。
2.3.1 到磁碟的路徑
要瞭解關於資料丟失和一致性的問題,我們要看看一個資料區塊是如何被送到磁碟的。說明了這是如何工作的:
當PostgreSQL要讀取或者寫入一個塊是,它通常要經過幾個層次。當一個塊被寫入,它將被發送到作業系統。作業系統將快取資料並對資料執行寫操作。在有些時候,作業系統將決定把資料傳到一些低層次。這可能是磁碟控制卡。磁碟控制卡將緩衝,重新排序,在資料最終到真實的實體儲存體裝置之前,可能還有一個緩衝層。
在我們的例子中,我們使用了四層。在許多企業級系統中,甚至可能有更多的層次。試想一個虛擬機器,儲存通過網路掛載,例如,SAN,NAS,NFS,ATA-over_Ethernet,iSCSI,等等。許多抽象層都會有資料通過,並且每層都將嘗試做自己那部分的最佳化。
從記憶體到記憶體
當PostgreSQL給作業系統傳遞一個8K的塊時,發生了什嗎?這個問題唯一正確的答案可能是:“有事情”。當一個到檔案的寫被執行時,絕對不能保證資料被實際送到磁碟。
在現實中,寫入檔案無非就是從PostgreSQL記憶體的複製操作到一些系統記憶體。這兩個記憶體地區都在記憶體中,因此,在崩潰的情況下,東西可能丟失。從實踐上來說,如果整個記憶體由於故障而不能工作,誰丟失了資料沒有什麼區別。
下面的程式碼片段說明了我們所面臨的基本問題:
test=# \d t_test
Table "public.t_test"
Column | Type | Modifiers
--------+---------+-----------
id | integer |
test=# BEGIN;
BEGIN
test=# INSERT INTO t_test VALUES (1);
INSERT 0 1
test=# COMMIT;
COMMIT
就像在前面章節中,我們使用只有一列的表。目標是運行一個插入一行的事務。
如果在提交不久之後,發生了崩潰,沒有資料會處於危險之中,因為什麼都沒有發生。如果崩潰在一個INSERT語句之後,但在COMMIT之前,沒有什麼會發生。使用者還沒有發出COMMIT,因此該事務是眾所周知的要運行,但沒有完成。如果發生崩潰,應用程式將注意到事情是不成功的,並(希望)做出相應的反應。
然而,情況是完全不同的,如果使用者已經發出了COMMIT語句,它已經成功返回。無論發生什麼,使用者將期望提交的資料是可用的。
[使用者期望成功的寫入在意外重新啟動後是可用的。所謂的ACID標準也要求持久性。在電腦科學中,ACID(原子性,一致性,隔離性,耐久性)是一組屬性,這些屬性保證資料庫事務可靠地處理。]
從記憶體到磁碟
要確保核心將資料從記憶體傳遞到磁碟,PostgreSQL必須採取一些預防措施。在 COMMIT,系統調用將被發起,它強制資料到交易記錄中。
[在這一點上,PostgreSQL沒有必要強制資料到資料檔案,因為我們總能從XLOG修複壞的資料檔案。如果資料被安全地儲存在XLOG中,事務可以被認為是安全。]
必要的強制資料到磁碟的系統調用是fsync()。一些列表是從BSD手冊頁複製過來的。在我們看來,這是所寫過的處理這個主題的最好的手冊頁之一:
FSYNC(2) BSD System Calls Manual FSYNC(2)
NAME
fsync -- synchronize a file‘s in-core state with
that on disk
SYNOPSIS
#include <unistd.h>
int fsync(intfildes);
DESCRIPTION
Fsync() causes all modified data and attributes of fildes to be moved to a permanent storage device.This normally results in all in-core modified
copies of buffers for the associated file to be written to a disk.
Note that while fsync() will flush all data from the host to the drive (i.e. the "permanent storage device"), the drive itself may not physically
write the data to the platters for quite some time and it may be written in an out-of-order sequence.Specifically, if the drive loses power or the OS
crashes, the application may find that only some or none of their data was written. The disk drive may also re-order the data so that later writes
may be present, while earlier writes are not.This is not a theoretical edge case. This scenario is easily reproduced with real world workloads
and drive power failures.
它本質上說,核心試圖使它在記憶體中檔案的映像與磁碟上的檔案映像一致。它通過所有的改變到存放裝置來實現。它也清楚地指出,我們在這裡不是在談論一個理論情境,刷回磁碟是一個非常重要的話題。
在COMMIT沒有磁碟排清,您根本無法確保您的資料安全,這意味著,在非常麻煩的情況下,您實際上會遺失資料。
而且,本質上重要的是速度和一致性;它們實際上是相對立的工作。刷回改變到磁碟尤其昂貴,因為這涉及到真實的硬體。我們的開銷並不是5%,而是多了很多。隨著SSD的引進,開銷已經大幅下降,但是它仍然是可觀的。
關於電池的一句話
大多數生產伺服器將使用RAID控制器來管理磁碟。這裡重要的一點是,磁碟排清和效能通常和RAID控制器關係較緊密。如果RAID控制器沒有電池,這是通常的情況,那麼它需要長時間瘋狂地重新整理。RAID控制器必須等待最慢的磁碟的返回。然而,如果電池是可用的話,RAID控制器可以假定一個功率損耗,不會阻止一旦電被恢複的話一個公認的磁碟寫完成。這樣控制器可以緩衝寫和簡單地偽裝重新整理。因此,一個簡單的電池可以很容易地將效能提高十倍。
[請記住,我們在本節所闡述的是一般的問題。但是,每個硬體都是不同的。我們強烈推薦您檢查和瞭解您的硬體以及RAID配置,看看重新整理是如何處理的。]
超越 fsync()
fsync()不是唯一把資料重新整理到磁碟的系統調用。根據您正在使用的作業系統,不同的重新整理調用都是可用的。在PostgreSQL中您可以通過改變wal_sync_method來決定您首選的重新整理系統。同樣,這個改變可以通過調整postgresql.conf來進行。
可用的方法是 open_datasync, fdatasync, fsync, fsync_writethrough, 以及 open_sync。
[如果您要改變這些值,我們強烈建議您查看您正在使用的作業系統的手冊頁,以確保您已經做了正確的選擇。]
2.3.2 PostgreSQL的一致性層級
確保一致性和防止資料丟失是昂貴的;每個磁碟排清都是昂貴的,在重新整理到磁碟之前,我們應該三思而後行。為了給使用者選擇,PostgreSQL提供了多種層級的資料保護。這些不同的選擇由兩個重要的參數代表,這可以在postgresql.conf中找到:
1. fsync
2. synchronous_commit
如果fsync被使用的話,fsync參數將控制資料丟失。在預設配置中,PostgreSQL將始終重新整理提交到磁碟。如果fsync處於關閉狀態,然而,不能保證COMMIT會倖免於崩潰。資料會丟失,甚至可能會有資料損毀。要保護您的資料,保持fsync處於開啟的狀態是必須的。如果您能承受失去一部分或者全部資料,您可以放鬆重新整理標準。
synchronous_commit和XLOG-writing 相關。通常情況下, PostgreSQL 將等待,直到資料已完全被寫入到XLOG。尤其是短事務可以承受的相當多,因此,提供了各種不同的選擇:
• on: PostgreSQL將一直等到 XLOG 已經完全成功地寫入。 如果您要儲存信用卡資料,您要確保金融事務部丟失。在這種情況下,重新整理到磁碟是必不可少的。
• off: 在給客戶報告成功和安全地寫入磁碟之間有一個時間差。在這樣的情況下,可以有損壞。讓我們假設一個儲存在一個網站上當前誰線上的資料庫。假設您的系統崩潰了,20分鐘後又恢複了。您真的在乎您的資料嗎?20分鐘後,每個人都有可能再次來回登入。這不值得犧牲效能來保護在幾分鐘後就過時的資料。
• local:在複製資料庫執行個體的情況下,我們將只等待本地執行個體重新整理到磁碟。這裡的好處是,您有一個進階別的保護,因為您重新整理到一個磁碟;然而,我們可以放心地假設不會有兩台伺服器同時崩潰,因此我們可以就可以放鬆一點slave 上的標準。
• remote_write: PostgreSQL 將一直等到同步待命伺服器為給定的事務報告成功。
在協議中設定fsync 為 off,改變 synchronous_commit 為 off 將不會導致崩潰。然而,在崩潰的情況下,我們可能會丟失一些事務,它們已經被成功提交了。 潛在的資料丟失的數量由一個額外的 postgresql.conf 中叫 wal_writer_delay管理。在把synchronous_commit 設定為off的情況下, 我們失去的永遠都不會比在wal_writer_delayconfig變數中定義的多。
[更改synchronous_commit 可能看起來像一個小的效能調整;然而,在現實中,當運行次小的寫事務時,更改 sync 行為是主導因素之一,增益可能不只有幾個百分點,但是,如果您幸運的話,它可能是十倍或者甚至更多(取決於硬體,工作負載,I/O子系統,等等)。]
請記住,設定資料庫不只是速度。一致性至少和速度同樣重要,因此,您應該仔細考慮您是否要用潛在的資料丟失來和速度交換。
因此,完全理解本章中所述的這些一致性相關的主題是非常重要的。當涉及到您的叢集架構,資料安全將是一個重要的組成部分,能夠判斷是否特定架構對您資料有意義是非常可取的。畢竟,資料庫的工作就是保護資料。您的耐久性要求的意識絕對是一個大的好處。
原文地址:http://www.cnblogs.com/songyuejie/p/4743332.html
PostgreSQL Replication之第二章 理解PostgreSQL的交易記錄(3)