W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
在任何時間,PostgreSQL在數(shù)據(jù)集簇目錄的pg_wal/
子目錄下都保持有一個預(yù)寫式日志(WAL)。這個日志存在的目的是為了保證崩潰后的安全:如果系統(tǒng)崩潰,可以“重放”從最后一次檢查點以來的日志項來恢復(fù)數(shù)據(jù)庫的一致性。該日志的存在也使得第三種備份數(shù)據(jù)庫的策略變得可能:我們可以把一個文件系統(tǒng)級別的備份和WAL文件的備份結(jié)合起來。當(dāng)需要恢復(fù)時,我們先恢復(fù)文件系統(tǒng)備份,然后從備份的WAL文件中重放來把系統(tǒng)帶到一個當(dāng)前狀態(tài)。這種方法比之前的方法管理起來要更復(fù)雜,但是有其顯著的優(yōu)點:
我們不需要一個完美的一致的文件系統(tǒng)備份作為開始點。備份中的任何內(nèi)部不一致性將通過日志重放(這和崩潰恢復(fù)期間發(fā)生的并無顯著不同)來修正。因此我們不需要文件系統(tǒng)快照功能,只需要tar或一個類似的歸檔工具。
由于我們可以結(jié)合一個無窮長的WAL文件序列用于重放,可以通過簡單地歸檔WAL文件來達(dá)到連續(xù)備份。這對于大型數(shù)據(jù)庫特別有用,因為在其中不方便頻繁地進(jìn)行完全備份。
并不需要一直重放WAL項一直到最后。我們可以在任何點停止重放,并得到一個數(shù)據(jù)庫在當(dāng)時的一致快照。這樣,該技術(shù)支持時間點恢復(fù):在得到你的基礎(chǔ)備份以后,可以將數(shù)據(jù)庫恢復(fù)到它在其后任何時間的狀態(tài)。
如果我們連續(xù)地將一系列WAL文件輸送給另一臺已經(jīng)載入了相同基礎(chǔ)備份文件的機器,我們就得到了一個熱后備系統(tǒng):在任何時間點我們都能提出第二臺機器,它差不多是數(shù)據(jù)庫的當(dāng)前副本。
pg_dump和pg_dumpall不會產(chǎn)生文件系統(tǒng)級別的備份,并且不能用于連續(xù)歸檔方案。這類轉(zhuǎn)儲是邏輯的并且不包含足夠的信息用于WAL重放。
就簡單的文件系統(tǒng)備份技術(shù)來說,這種方法只能支持整個數(shù)據(jù)庫集簇的恢復(fù),卻無法支持其中一個子集的恢復(fù)。另外,它需要大量的歸檔存儲:一個基礎(chǔ)備份的體積可能很龐大,并且一個繁忙的系統(tǒng)將會產(chǎn)生大量需要被歸檔的WAL流量。盡管如此,在很多需要高可靠性的情況下,它是首選的備份技術(shù)。
要使用連續(xù)歸檔(也被很多數(shù)據(jù)庫廠商稱為“在線備份”)成功地恢復(fù),你需要一個從基礎(chǔ)備份時間開始的連續(xù)的歸檔WAL文件序列。為了開始,在你建立第一個基礎(chǔ)備份之前,你應(yīng)該建立并測試用于歸檔WAL文件的過程。對應(yīng)地,我們首先討論歸檔WAL文件的機制。
抽象地來說,一個運行中的PostgreSQL系統(tǒng)產(chǎn)生一個無窮長的WAL記錄序列。系統(tǒng)從物理上將這個序列劃分成WAL 段文件,通常是每個16MB(段尺寸在initdb期間可修改)。段文件會被分配一個數(shù)字名稱以便反映它在整個抽象WAL序列中的位置。在沒有使用WAL歸檔時,系統(tǒng)通常只創(chuàng)建少量段文件,并且通過重命名不再使用的段文件為更高的段編號來 “回收”它們。系統(tǒng)假設(shè)內(nèi)容位于最后一個檢查點之前的段文件是無用的且可以被回收。
在歸檔WAL數(shù)據(jù)時,我們需要在每一段被填充滿時捕捉其內(nèi)容,并且在段文件被回收重用之前保存該數(shù)據(jù)。依靠應(yīng)用和可用的硬件,有很多不同的方法來“保存數(shù)據(jù)”:我們可以將段文件拷貝到一個已掛載的位于另一臺機器上的NFS目錄,或者將它們寫出到一個磁帶驅(qū)動器(確保你有辦法標(biāo)識每個文件的原始文件名),或者將它們批量燒錄到CD上,或者其他什么方法。為了向數(shù)據(jù)庫管理員提供靈活性,PostgreSQL不對如何歸檔做任何假設(shè)。取而代之的是,
PostgreSQL讓管理員聲明一個shell命令來拷貝一個完整的段文件到它需要去的地方。 該命令可以簡單得就是一個cp
,或者它可以調(diào)用一個復(fù)雜的 shell 腳本 — 所有都由你決定。
要啟用WAL歸檔,需設(shè)置wal_level配置參數(shù)為replica
或更高,設(shè)置archive_mode為on
,并且使用
archive_command配置參數(shù)指定一個shell命令。實際上,這些設(shè)置總是被放置在postgresql.conf
文件中。在archive_command
中,%p
會被將要歸檔的文件路徑所替代,而%f
只會被文件名所替代(路徑名是相對于當(dāng)前工作目錄而言的,即集簇的數(shù)據(jù)目錄)。如果你需要在命令中嵌入一個真正的
%
字符,可以使用%%
。最簡單的命令類似于:
archive_command = 'test ! -f /mnt/server/archivedir/%f && cp %p /mnt/server/archivedir/%f' # Unix
archive_command = 'copy "%p" "C:\\server\\archivedir\\%f"' # Windows
它將把 WAL 段拷貝到目錄/mnt/server/archivedir
(這個只是一個例子,并非我們建議的方法,可能不能在所有系統(tǒng)上都正確運行)。在%p
和%f
參數(shù)被替換之后,實際被執(zhí)行的命令看起來可能是:
test ! -f /mnt/server/archivedir/00000001000000A900000065 && cp pg_wal/00000001000000A900000065 /mnt/server/archivedir/00000001000000A900000065
對每一個將要被歸檔的新文件都會生成一個類似的命令。
歸檔命令將在運行PostgreSQL服務(wù)器的同一個用戶的權(quán)限下執(zhí)行。因為被歸檔的一系列WAL 文件實際上包含你的數(shù)據(jù)庫里的所有東西,所以你應(yīng)該確保自己的歸檔數(shù)據(jù)不會被別人窺探; 比如,歸檔到一個沒有組或者全局讀權(quán)限的目錄里。
有一點很重要:當(dāng)且僅當(dāng)歸檔命令成功時,它才返回零退出。在得到一個零值結(jié)果之后,PostgreSQL將假設(shè)該文件已經(jīng)成功歸檔, 因此它稍后將被刪除或者被新的數(shù)據(jù)覆蓋。但是,一個非零值告訴PostgreSQL該文件沒有被歸檔; 因此它會周期性的重試直到成功。
歸檔命令通常應(yīng)該被設(shè)計成拒絕覆蓋已經(jīng)存在的歸檔文件。這是一個非常重要的安全特性, 可以在管理員操作失誤(比如把兩個不同的服務(wù)器的輸出發(fā)送到同一個歸檔目錄)的時候保持你的歸檔的完整性。
我們建議你首先要測試你準(zhǔn)備使用到歸檔命令,以保證它實際上不會覆蓋現(xiàn)有的文件,并且在這種情況下它返回非零狀態(tài)。以上Unix中的命令例子通過包含一個獨立的test
步驟來保證這一點。在某些Unix平臺上,cp
具有諸如-i
的開關(guān),可用來更簡潔地完成這一切,但是在沒有驗證返回的退出狀態(tài)正確之前你不能依賴它們(特別地,GNU的
cp
在使用-i
時將對已存在的目標(biāo)文件返回狀態(tài)零,這并不是我們所期望的行為)。
在設(shè)計你的歸檔環(huán)境時,請考慮一下如果歸檔命令不停失敗會發(fā)生什么情況, 因為有些情況要求操作者的干涉,或者是歸檔空間不夠了。 例如,如果你往磁帶機上寫,但是沒有自動換帶機,那么就有可能發(fā)生這種情況; 如果磁帶滿了,除非換磁帶,否則任何事也做不了。 你應(yīng)該確保任何錯誤情況或者任何要求操作員干涉的情況都會被正確報告, 這樣才能迅速解決這些問題。否則pg_wal/
目錄會不停地被WAL段文件填充,直到問題解決(如果包含pg_wal/
的文件系統(tǒng)被填滿,
PostgreSQL將會做一次致命關(guān)閉。不會有未提交事務(wù)被丟失,但是數(shù)據(jù)庫將會保持離線直到你釋放一部分空間)。
歸檔命令的速度并不要緊,只要它能跟上你的服務(wù)器生成 WAL 數(shù)據(jù)的平均速度即可。即使歸檔進(jìn)程稍微落后,正常的操作也會繼續(xù)進(jìn)行。 如果歸檔進(jìn)程慢很多,就會增加災(zāi)難發(fā)生的時候丟失的數(shù)據(jù)量。這同時也意味著pg_wal/
目錄包含大量未歸檔的段文件, 并且可能最后超出了可用磁盤空間。我們建議你監(jiān)控歸檔進(jìn)程,確保它是按照你的期望運轉(zhuǎn)的。
在寫自己的歸檔命令的時候,你應(yīng)該假設(shè)被歸檔的文件名最長為64個字符并且可以包含 ASCII 字母、數(shù)字以及點的任意組合。 我們不需要保持原始的相對路徑(%p
),但是有必要保持文件名(%f
)。
請注意盡管 WAL 歸檔允許你恢復(fù)任何對你的PostgreSQL數(shù)據(jù)庫中數(shù)據(jù)所做的修改, 但它不會恢復(fù)對配置文件的修改(即postgresql.conf
、pg_hba.conf
以及pg_ident.conf
),因為這些文件都是手工編輯的,而不是通過 SQL
操作來編輯的。 所以你可能會需要把你的配置文件放在一個日常文件系統(tǒng)備份過程可處理的位置。如何重定位配置文件請參閱第 19.2 節(jié)。
歸檔命令只會為完成的WAL段調(diào)用。因此如果你的服務(wù)器產(chǎn)生了一點點WAL流量(或者在產(chǎn)生時有寬松的周期),從一個事務(wù)完成到它被安全地記錄在歸檔存儲中之間將會有較長的延遲。要為未歸檔數(shù)據(jù)設(shè)置一個年齡限制,你可以設(shè)置archive_timeout來強制要求服務(wù)器按照其設(shè)定的頻度切換到一個新的WAL段。注意由于強制切換而被歸檔的文件還是具有和完全歸檔的文件相同的長度。因此設(shè)置一個很短的
archive_timeout
是很不明智的 — 它會膨脹你的歸檔存儲。將archive_timeout
設(shè)置為1分鐘左右通常是合理的。
同樣,如果你希望確保一個剛剛完成的事務(wù)能被盡快歸檔,可以使用pg_switch_wal
進(jìn)行一次手動段切換。其他與WAL管理相關(guān)的使用函數(shù)在表 9.85中列出。
如第 14.4.7 節(jié)所述,當(dāng)wal_level
為minimal
時,一些SQL命令被優(yōu)化為避免記錄WAL日志。在這些語句的其中之一的執(zhí)行過程中如果打開了歸檔或流復(fù)制,WAL中將不會包含足夠的信息用于歸檔恢(崩潰恢復(fù)不受影響)。出于這個原因,
wal_level
只能在服務(wù)器啟動時修改。但是,archive_command
可以通過重載配置文件來修改。如果你希望暫時停止歸檔,一種方式是將archive_command
設(shè)置為空串(''
)。這將導(dǎo)致WAL文件積累在pg_wal/
中,直到一個可用的
archive_command
被重新建立。
執(zhí)行一次基礎(chǔ)備份最簡單的方法是使用pg_basebackup工具。它將會以普通文件或一個tar歸檔的方式創(chuàng)建一個基礎(chǔ)備份。如果需要比pg_basebackup更高的靈活性,你也可以使用低級API(見本文中第 25.3.3 節(jié))來制作一個基礎(chǔ)備份。
沒有必要關(guān)心創(chuàng)建一個基礎(chǔ)備份所需的時間。但是,如果你正常地運行停用了full_page_writes
的服務(wù)器,你可能會注意到備份運行時的性能下降,因為full_page_writes
在備份模式期間會被實際強制實施。
要使用備份,你將需要保留所有在文件系統(tǒng)備份期間及之后生成的WAL段文件。為了便于你做這些,基礎(chǔ)備份過程會創(chuàng)建一個備份歷史文件,它將被立刻存儲到WAL歸檔區(qū)域。該文件以文件系統(tǒng)備份中你需要的第一個WAL段文件命名。例如,如果開始的WAL文件是0000000100001234000055CD
,則備份歷史文件將被命名為0000000100001234000055CD.007C9330.backup
.(文件名的第二部分表明WAL文件中的一個準(zhǔn)確位置,一般可以被忽略)。一旦你已經(jīng)安全地歸檔了文件系統(tǒng)備份和在備份過程中被使用的WAL段文件(如備份歷史文件中所指定的)
,所有名字在數(shù)字上低于備份歷史文件中記錄值的已歸檔WAL段對于恢復(fù)文件系統(tǒng)備份就不再需要了,并且可以被刪除。但是你應(yīng)該考慮保持多個備份集以絕對保證你能恢復(fù)你的數(shù)據(jù)。
備份歷史文件是一個很小的文本文件。它包含你指定給pg_basebackup的標(biāo)簽字符串,以及備份的起止時間以及起止WAL段。如果你使用該標(biāo)簽來標(biāo)識相關(guān)轉(zhuǎn)儲文件,則已歸檔的歷史文件足以說明需要哪個轉(zhuǎn)儲文件進(jìn)行恢復(fù)。
由于你不得不保存最后一次基礎(chǔ)備份之后的所有歸檔WAL文件,基礎(chǔ)備份之間的間隔通常應(yīng)該根據(jù)你希望在歸檔WAL文件上花費的存儲空間來設(shè)定。你也應(yīng)該考慮你準(zhǔn)備花多長時間來進(jìn)行恢復(fù),如果需要恢復(fù) — 系統(tǒng)將不得不重放所有那些WAL段,如果這些WAL段覆蓋了最后一次基礎(chǔ)備份以后的很長時間,重放過程將會花費一些時間。
使用低級API制作一個基礎(chǔ)備份的過程比pg_basebackup方法要包含更多的步驟,但相對要更簡單。很重要的一點是,這些步驟要按照順序執(zhí)行,并且在執(zhí)行下一步之前要驗證上一步是否成功。
可以用非排他或者排他的方法來制作低級基礎(chǔ)備份。我們推薦非排他方法,而排他 的方法已經(jīng)被廢棄并且最終將被去除。
非排他低級備份允許其他并發(fā)備份運行(既包括那些使用同樣的 備份 API 開始的備份,也包括那些使用 pg_basebackup開始的備份)。
確保WAL歸檔被啟用且正在工作。
作為一個具有運行 pg_start_backup 權(quán)利的用戶(超級用戶,或者被授予在該 函數(shù)上 EXECUTE 的用戶)連接到服務(wù)器(不在乎是哪個數(shù)據(jù)庫)并且發(fā)出命令:
SELECT pg_start_backup('label', false, false);
其中label
是用來唯一標(biāo)識這次備份操作的任意字符串。調(diào)用 pg_start_backup
的連接必須被保持到備份結(jié)束,否則備份 將被自動中止。
默認(rèn)情況下,pg_start_backup
可能需要較長的時間完成。 這是因為它會執(zhí)行一個檢查點,并且該檢查點所需要的 I/O 將會分散到一段 顯著的時間上,默認(rèn)情況下是你的檢查點間隔(見配置參數(shù) checkpoint_completion_target)的一半。這通常 是你所想要的,因為它可以最小化對查詢處理的影響。如果你想要盡可能快地
開始備份,請把第二個參數(shù)改成true
,這將會發(fā)出一個立即的檢查點并且使用盡可能多的I/O。
第三個參數(shù)為false
會告訴pg_start_backup
開始一次非排他基礎(chǔ)備份。
使用任何趁手的文件系統(tǒng)備份工具(例如tar或者 cpio,不是pg_dump 或者pg_dumpall)執(zhí)行備份。當(dāng)你做這些 時,不需要也不值得停止正常的數(shù)據(jù)庫操作。在這類備份期間要考慮的事情 請見本文中第 25.3.3.3 節(jié)。
在同一個連接中,發(fā)出命令:
SELECT * FROM pg_stop_backup(false);
這會終止備份模式。在主控機上,它還執(zhí)行一次自動切換到下一個WAL段。在后備機上,它無法自動切換WAL段,因此用戶可能希望在主控機上運行pg_switch_wal
來執(zhí)行一次手工切換。要做切換的原因是讓在備份期間寫入的最后一個WAL段文件能準(zhǔn)備好被歸檔。
pg_stop_backup
將返回一個具有三個值的行。這些域的 第二個應(yīng)該被寫入到該備份根目錄中名為backup_label
的 文件。第三個域應(yīng)該被寫入到一個名為tablespace_map
的文件,除非該域為空。這些文件對該備份正常工作來說是至關(guān)重要的, 不能被隨意修改。
一旦備份期間活動的WAL段文件被歸檔,備份就完成了。由 pg_stop_backup
的第一個返回值標(biāo)識的文件是構(gòu)成一個 完整備份文件集合所需的最后一個段。在主控機上,如果archive_mode
被啟用并且wait_for_archive
參數(shù)為true
,在最后一個段被歸檔之前
pg_stop_backup
都不會返回。在后備機上,為了讓pg_stop_backup
等待,archive_mode
必須為always
。從你已經(jīng)配置好archive_command
之后這些文件的 歸檔就會自動發(fā)生。在大部分情況下,這些歸檔會很快發(fā)生,但是建議你監(jiān)
控你的歸檔系統(tǒng)確保沒有延遲。如果歸檔進(jìn)程由于歸檔命令的失敗而落后, 它將會持續(xù)重試知道歸檔成功并且備份完成。如果你希望對 pg_stop_backup
的執(zhí)行給出一個時間限制,可以設(shè)置一個 合適的statement_timeout
值,但要注意如果 pg_stop_backup
因此而中止會致使備份可能失效。
如果備份進(jìn)程監(jiān)控并且確保備份所需的所有WAL段文件都被成功地歸檔,那么wait_for_archive
參數(shù)(默認(rèn)為true)可以被設(shè)置為false,以便pg_stop_backup
在停止備份記錄被寫入到WAL后立即返回。默認(rèn)情況下,pg_stop_backup
將會等待,直至所有WAL都被歸檔,這種等待會花一段時間。這個選項必須被小心地使用:如果WAL歸檔沒有被正確的監(jiān)控,則備份可能沒有包括所有的WAL文件并且因此將變得不完整和不可恢復(fù)。
排他式備份方法已過時,應(yīng)避免使用。 在PostgreSQL 9.6 之前,這是唯一可用的低級方法,但是現(xiàn)在 推薦所有用戶升級他們的腳本來使用非排他備份。
一個排他備份的處理絕大部分都和非排他備份相同,但是在一些關(guān)鍵步驟上不同。這種備份只能在主控機上制作,并且不允許并發(fā)備份。而且,由于它像如下所述的那樣創(chuàng)建一個備份標(biāo)簽文件,所以會阻止崩潰后主服務(wù)器的自動重啟。另一方面,從備份或后備中刪除該文件是常見的錯誤,會導(dǎo)致嚴(yán)重的數(shù)據(jù)損壞。如果需要用此方法,可使用下述步驟。
確保 WAL 歸檔被啟用且正常工作。
作為一個具有運行 pg_start_backup 權(quán)利的用戶(超級用戶,或者被授予在該 函數(shù)上 EXECUTE 的用戶)連接到服務(wù)器(不在乎是哪個數(shù)據(jù)庫)并且發(fā)出命令:
SELECT pg_start_backup('label');
這里label
是任何你希望用來唯一標(biāo)識這個備份操作的字符串。 pg_start_backup
在集簇目錄中創(chuàng)建一個關(guān)于備份信息的 備份標(biāo)簽文件,也被稱為backup_label
, 其中包括了開始時間和標(biāo)簽字符串。該函數(shù)也會在集簇目錄中創(chuàng)建一個 名為tablespace_map
的
表空間映射文件, 如果在pg_tblspc/
中有一個或者多個表空間符號鏈接存在, 該文件會包含它們的信息。如果你需要從備份中恢復(fù),這兩個文件對于備份的 完整性都至關(guān)重要。
默認(rèn)情況下,pg_start_backup
會花費很長時間來完成。這是因為它會執(zhí)行一個檢查點,而檢查點所需要的I/O在相當(dāng)一段時間內(nèi)將會被傳播,默認(rèn)情況下這段時間是內(nèi)部檢查點間隔的一半(參見配置參數(shù)checkpoint_completion_target)。這通常是你所希望的,因為它能將對查詢處理的影響最小化。如果你要盡快開始備份,可使用:
SELECT pg_start_backup('label', true);
這會使檢查點盡可能快地被完成。
使用任何方便的文件系統(tǒng)備份工具執(zhí)行備份,例如tar 或cpio(不是pg_dump 或pg_dumpall)。在此期間,不需要也 不值得停止正常的數(shù)據(jù)庫操作。在備份期間要考慮的事情可見 本文中第 25.3.3.3 節(jié)小節(jié)。
如上所述,如果服務(wù)器在備份期間崩潰,它可能無法重啟,直至從PGDATA
目錄中手工地移除backup_label
文件。注意到在恢復(fù)備份時永遠(yuǎn)不要刪除backup_label
文件非常重要,因為這會導(dǎo)致?lián)p壞。使用此方法時,關(guān)于何時適合刪除該文件的困惑是導(dǎo)致數(shù)據(jù)損壞的常見原因;一定要確認(rèn)僅在現(xiàn)有的主服務(wù)器上刪除該文件,并且從未在構(gòu)建后備或恢復(fù)備份時刪除,即使你正在構(gòu)建后備服務(wù)器,而后該后備服務(wù)器會提升為新的主服務(wù)器。
再次以具有運行 pg_stop_backup 權(quán)利的用戶(超級用戶,或者已經(jīng)被授予 該函數(shù)上 EXECUTE 的用戶)連接到數(shù)據(jù)庫并且發(fā)出命令:
SELECT pg_stop_backup();
這個函數(shù)將終止備份模式,并且執(zhí)行一個自動切換到下一個WAL段。進(jìn)行切換的原因是將在備份期間生成的最新WAL段文件安排為可歸檔。
一旦備份期間活動的WAL段文件被歸檔,你的工作就完成了。 pg_stop_backup
的結(jié)果所標(biāo)識的文件是構(gòu)成一個完整備份 文件組所需的最新段。如果archive_mode
被啟用,直到最 新段被歸檔pg_stop_backup
都不會返回。由于你已經(jīng)配置了 archive_command
,這些文件的歸檔過程會自動發(fā)生。在
大部分情況下這會很快發(fā)生,但還是建議你監(jiān)控你的歸檔系統(tǒng)來確保不會有 延遲。如果歸檔處理由于歸檔命令的錯誤而延遲,它會保持重試直到歸檔成 功和備份完成。
當(dāng)使用排他式備份時,絕對要確保備份最后階段pg_stop_backup
成功執(zhí)行。即使備份本身失敗,例如由于缺少磁盤空間,調(diào)用pg_stop_backup
失敗,這樣就不確定服務(wù)器是否留在備份模式下,導(dǎo)致未來的備份失敗,增加了backup_label
存在期間重啟失敗的風(fēng)險。
如果被拷貝的文件在拷貝過程中發(fā)生變化,某些文件系統(tǒng)備份工具會發(fā)出警告或錯誤。在建立一個活動數(shù)據(jù)庫的基礎(chǔ)備份時,這種情況是正常的,并非一個錯誤。然而,你需要確保你能夠把它們和真正的錯誤區(qū)分開。例如,某些版本的rsync為“消失的源文件”返回一個獨立的退出碼,且你可以編寫一個驅(qū)動腳本來將該退出碼接受為一種非錯誤情況。同樣,如果一個文件在被
tar復(fù)制的過程中被截斷,某些版本的GNU tar會返回一個與致命錯誤無法區(qū)分的錯誤代碼。幸運的是,如果一個文件在備份期間被改變,版本為1.16及其后的GNU tar將會退出并返回1,而對于其他錯誤返回2。在版本1.23及其后的GNU tar中,你可以使用警告選項--warning=no-file-changed
--warning=no-file-removed
來隱藏相關(guān)的警告消息。
確認(rèn)你的備份包含數(shù)據(jù)庫集簇目錄(例如/usr/local/pgsql/data
)下的所有文件。如果你使用了不在此目錄下的表空間,注意也把它們包括在內(nèi)(并且確保你的備份將符號鏈接歸檔為鏈接,否則恢復(fù)過程將破壞你的表空間)。
不過,你應(yīng)當(dāng)從備份中忽略集簇的pg_wal/
子目錄中的文件。這種微小的調(diào)整是值得的,因為它降低了恢復(fù)時的錯誤風(fēng)險。如果pg_wal/
是一個指向位于集簇目錄之外其他地方的符號鏈接就很容易安排了,這是一種出于性能原因的常見設(shè)置。你可能也希望排除postmaster.pid
和postmaster.opts
,它們記錄了關(guān)于
postmaster運行的信息,但與最終使用這個備份的postmaster無關(guān)(這些文件可能會使pg_ctl搞混淆)。
從備份中忽略集簇的pg_replslot/
子目錄中的文件通常也是個好主意,這樣 主控機上存在的復(fù)制槽不會成為備份的一部分。否則,后續(xù)用該備份創(chuàng)建一個后備機可能會導(dǎo)致該 后備機上的WAL文件被無限期保留,并且在啟用了熱后備反饋的情況下可能導(dǎo)致主控機膨脹,因為使用 那些復(fù)制槽的客戶端將繼續(xù)連接到主控機(而不是后備機)并且繼續(xù)更新其上的槽。即使該備份是要被 用來創(chuàng)建一個新的主控機,拷貝復(fù)制槽也不是特別有用,因為這些槽的內(nèi)容在新主控機上線時很可能已
經(jīng)過時。
目錄pg_dynshmem/
、pg_notify/
、pg_serial/
、pg_snapshots/
、pg_stat_tmp/
和pg_subtrans/
的內(nèi)容(但不是這些目錄本身)可以從備份中省略,因為它們在postmaster啟動時會被初始化。如果
stats_temp_directory被設(shè)置并且位于數(shù)據(jù)目錄中,則該目錄的內(nèi)容也可以被省略。
任何以pgsql_tmp
開始的文件或目錄都可以從備份中省略。這些文件在postmaster啟動時會被移除,而目錄將被根據(jù)需要重建。
只要找到名為pg_internal.init
的文件,它就可以從備份中省略。這些文件包含關(guān)系緩沖數(shù)據(jù),它們在恢復(fù)時總是會被重建。
備份標(biāo)簽文件包含你指定給 pg_start_backup
的標(biāo)簽字符串,以及 pg_start_backup
被運行的時刻和起始WAL文件的名字。 在發(fā)生混亂的情況下就可以在備份文件中查看并準(zhǔn)確地決定該轉(zhuǎn)儲文件來 自于哪個備份會話。表空間映射文件包括存在于目錄pg_tblspc/
中的符號鏈接名稱以及每一個符號鏈接的完整路徑。這些文件不僅是為了供參考,
它們的存在和內(nèi)容對于系統(tǒng)恢復(fù)過程的正確操作是至關(guān)重要。
在服務(wù)器停止時也可以創(chuàng)建一個備份。在這種情況下,你顯然不能使用 pg_start_backup
或pg_stop_backup
, 并且因此你只能依靠你的自己的策略來跟蹤哪個備份是哪個, 以及相關(guān)WAL文件應(yīng)該走回到什么程度。通常最好遵循上面的連續(xù)歸檔過程。
好,現(xiàn)在最壞的情況發(fā)生了,你需要從你的備份進(jìn)行恢復(fù)。這里是其過程:
如果服務(wù)器仍在運行,停止它。
如果你具有足夠的空間,將整個集簇數(shù)據(jù)目錄和表空間復(fù)制到一個臨時位置,稍后你將用到它們。注意這種預(yù)防措施將要求在你的系統(tǒng)上有足夠的空閑空間來保留現(xiàn)有數(shù)據(jù)庫的兩個拷貝。如果你沒有足夠的空間,你至少要保存集簇的pg_wal
子目錄的內(nèi)容,因為它可能包含在系統(tǒng)垮掉之前還未被歸檔的日志。
移除所有位于集簇數(shù)據(jù)目錄和正在使用的表空間根目錄下的文件和子目錄。
從你的文件系統(tǒng)備份中恢復(fù)數(shù)據(jù)庫文件。注意它們要使用正確的所有權(quán)恢復(fù)(數(shù)據(jù)庫系統(tǒng)用戶,不是root
?。┎⑶沂褂谜_的權(quán)限。如果你在使用表空間,你應(yīng)該驗證pg_tblspc/
中的符號鏈接被正確地恢復(fù)。
移除pg_wal/
中的任何文件,這些是來自于文件系統(tǒng)備份而不是當(dāng)前日志,因此可以被忽略。如果你根本沒有歸檔pg_wal/
,那么以正確的權(quán)限重建它。注意如果以前它是一個符號鏈接,請確保你也以同樣的方式重建它。
如果你有在第2步中保存的未歸檔WAL段文件,把它們拷貝到pg_wal/
(最好是拷貝而不是移動它們,這樣如果在開始恢復(fù)后出現(xiàn)問題你任然有未修改的文件)。
設(shè)定postgresql.conf
(見第 19.5.4 節(jié))中的恢復(fù)配置設(shè)置,并且在集簇數(shù)據(jù)目錄中創(chuàng)建一個recovery.signal
文件。你可能還想臨時修改
pg_hba.conf
來阻止普通用戶在成功恢復(fù)之前連接。
啟動服務(wù)器。服務(wù)器將會進(jìn)入到恢復(fù)模式并且進(jìn)而根據(jù)需要讀取歸檔WAL文件?;謴?fù)可能因為一個外部錯誤而被終止,可以簡單地重新啟動服務(wù)器,這樣它將繼續(xù)恢復(fù)。恢復(fù)過程結(jié)束后,服務(wù)器將刪除recovery.signal
(為了阻止以后意外地重新進(jìn)入恢復(fù)模式),并且開始正常數(shù)據(jù)庫操作。
檢查數(shù)據(jù)庫的內(nèi)容來確保你已經(jīng)恢復(fù)到了期望的狀態(tài)。如果沒有,返回到第1步。如果一切正常,通過恢復(fù)pg_hba.conf
為正常來允許用戶連接。
所有這些的關(guān)鍵部分是設(shè)定一個恢復(fù)配置,它描述你希望如何恢復(fù)以及恢復(fù)要運行到什么程度。你絕對必須指定的是restore_command
,它告訴PostgreSQL如何獲取歸檔WAL文件段。與archive_command
相似,這也是一個shell命令字符串。它可以包含%f
(將被期望的日志文件名替換)和
%p
(將被日志文件被拷貝的目標(biāo)路徑名替換)。(路徑名是相對于當(dāng)前工作目錄的,即集簇的數(shù)據(jù)目錄)。如果你需要在命令中嵌入一個真正的%
字符,可以寫成%%
。最簡單的命令類似于:
restore_command = 'cp /mnt/server/archivedir/%f %p'
它將從目錄/mnt/server/archivedir
中拷貝之前歸檔的WAL段。當(dāng)然,你可以使用更復(fù)雜的,甚至是一個要求操作者裝載合適磁帶的shell腳本。
重要的是命令在失敗時返回非零退出狀態(tài)。該命令將被調(diào)用來請求不在歸檔中的文件, 在這種情況下它應(yīng)該返回非零值。這不是一種錯誤情況。一種例外是該命令被一個信號(除了被用作數(shù) 據(jù)庫服務(wù)器關(guān)閉動作一部分的SIGTERM)終止或者被shell的錯誤 (例如命令未找到)終止,那樣恢復(fù)將中止并且服務(wù)器將不會啟動。
并非所有被請求的文件都是WAL段文件,你也許還會請求一些具有.history
后綴的文件。還要注意的是,%p
路徑的基本名字將會和%f
不同,但不要期望它們可以互換。
歸檔中找不到的WAL段可以在pg_wal/
中看到,這使得可以使用最近未歸檔的段。但是,在歸檔中可用的段將會被優(yōu)先于pg_wal/
中的文件被使用。
通常,恢復(fù)將會處理完所有可用的WAL段,從而將數(shù)據(jù)庫恢復(fù)到當(dāng)前時間點(或者盡可能接近給定的可 用WAL段)。因此,一個正常的恢復(fù)將會以一個“文件未找到”消息結(jié)束,錯誤消息的準(zhǔn)確文 本取決于你選擇的restore_command
。你也可能在恢復(fù)的開始看到一個針對名稱類 似于00000001.history
文件的錯誤消息。這也是正常的并且不表示在簡單恢復(fù)情
況中的問題,對此的討論見本文中第 25.3.5 節(jié)。
如果你希望恢復(fù)到之前的某個時間點(例如,恢復(fù)到幼稚的DBA丟棄了你主要的交易表之前),只需要 指定要求的停止點。你可以使用日期/時間、命名恢復(fù)點或一個 指定事務(wù)ID的結(jié)束時間來定義停止點(也被稱為“恢復(fù)目標(biāo)”)。在這種寫法中,只有日期/時 間和命名恢復(fù)點選項非常有用,因為沒有工具可以幫助你準(zhǔn)確地確定要用哪個事務(wù)ID。
停止點必須位于基礎(chǔ)備份的完成時間之后,即pg_stop_backup
的完成時間。在備份過程中你不能使用基礎(chǔ)備份來恢復(fù)(要恢復(fù)到這個時間,你必須回到你之前的基礎(chǔ)備份并且從這里開始前滾)。
如果恢復(fù)找到被破壞的WAL數(shù)據(jù),恢復(fù)將會停止于該點并且服務(wù)器不會啟動。在這種情況下,恢復(fù)進(jìn)程需要從開頭重新開始運行,并指定一個在損壞點之前的“恢復(fù)目標(biāo)”以便恢復(fù)能夠正常完成。如果恢復(fù)由于一個外部原因失敗,例如一個系統(tǒng)崩潰或者WAL歸檔變?yōu)椴豢稍L問,則該次恢復(fù)可以被簡單地重啟并且它將會從幾乎是上次失敗的地方繼續(xù)?;謴?fù)重啟工作起來很像普通操作時的檢查點:服務(wù)器周期性地強制把它的所有狀態(tài)寫到磁盤中,然后更新
pg_control
文件來說明已經(jīng)處理過的WAL數(shù)據(jù),這樣它們就不會被再次掃描。
將數(shù)據(jù)庫恢復(fù)到一個之前的時間點的能力帶來了一些復(fù)雜性,這和有關(guān)時間旅行和平行宇宙的科幻小說有些相似。例如,在數(shù)據(jù)庫的最初歷史中,假設(shè)你在周二晚上5:15時丟棄了一個關(guān)鍵表,但是一直到周三中午才意識到你的錯誤。不用苦惱,你取出你的備份,恢復(fù)到周二晚上5:14的時間點,并上線運行。在數(shù)據(jù)庫宇宙的這個歷史中,你從沒有丟棄該表。但是假設(shè)你后來意識到這并非一個好主意,并且想回到最初歷史中周三早上的某個時間。你沒法這樣做,在你的數(shù)據(jù)庫在線運行期間,它重寫了某些WAL段文件,而這些文件本來可以將你引向你希望回到的時間。因此,為了避免出現(xiàn)這種狀況,你需要將完成時間點恢復(fù)后生成的WAL記錄序列與初始數(shù)據(jù)庫歷史中產(chǎn)生的WAL記錄序列區(qū)分開來。
要解決這個問題,PostgreSQL有一個時間線概念。無論何時當(dāng)一次歸檔恢復(fù)完成,一個新的時間線被創(chuàng)建來標(biāo)識恢復(fù)之后生成的WAL記錄序列。時間線ID號是WAL段文件名的一部分,因此一個新的時間線不會重寫由之前的時間線生成的WAL數(shù)據(jù)。實際上可以歸檔很多不同的時間線。雖然這可能看起來是一個無用的特性,但是它常常扮演救命稻草的角色??紤]到你不太確定需要恢復(fù)到哪個時間點的情況,你可能不得不做多次時間點恢復(fù)嘗試和錯誤,直到最終找到從舊歷史中分支出去的最佳位置。如果沒有時間線,該處理將會很快生成一堆不可管理的混亂。而有了時間線,你可以恢復(fù)到 任何 之前的狀態(tài),包括早先被你放棄的時間線分支中的狀態(tài)。
每次當(dāng)一個新的時間線被創(chuàng)建,PostgreSQL會創(chuàng)建一個“時間線歷史”文件,它顯示了新時間線是什么時候從哪個時間線分支出來的。系統(tǒng)在從一個包含多個時間線的歸檔中恢復(fù)時,這些歷史文件對于允許系統(tǒng)選取正確的WAL段文件非常必要。因此,和WAL段文件相似,它們也要被歸檔到WAL歸檔區(qū)域。歷史文件是很小的文本文件,因此將它們無限期地保存起來的代價很小,而且也是很合適的(而段文件都很大)。如果你喜歡,你可以在一個歷史文件中增加注釋來記錄如何和為什么要創(chuàng)建該時間線。當(dāng)你由于試驗的結(jié)果擁有了一大堆錯綜復(fù)雜的不同時間線時,這種注釋將會特別有價值。
恢復(fù)的默認(rèn)行為是沿著相同的時間線進(jìn)行恢復(fù),該時間線是基礎(chǔ)備份創(chuàng)建時的當(dāng)前時間線。如果你希望恢復(fù)到某個子女時間線(即,你希望回到在一次恢復(fù)嘗試后產(chǎn)生的某個狀態(tài)),你需要在recovery_target_timeline中指定目標(biāo)時間線ID。你不能恢復(fù)到早于該基礎(chǔ)備份之前分支出去的時間線。
這里將給出一些配置連續(xù)歸檔的建議。
可以使用PostgreSQL的備份功能來產(chǎn)生單機熱備份。這些備份不能被用于時間點恢復(fù),然而備份和恢復(fù)時要比使用pg_dump轉(zhuǎn)儲更快(它們也比pg_dump轉(zhuǎn)儲更大,所以在某些情況下速度優(yōu)勢可能會被否定)。
在基礎(chǔ)備份的幫助下,產(chǎn)生一個單機熱備份最簡單的方式是使用pg_basebackup工具。如果你在調(diào)用它時使用了-X
參數(shù),使用該備份所需的所有事務(wù)日志將會被自動包含在該備份中,并且恢復(fù)該備份也不需要特殊的動作。
如果在復(fù)制備份文件時需要更多靈活性,也可以使用一個較低層的處理來創(chuàng)建單機熱備份。要為低層 單機熱備份做準(zhǔn)備,確保wal_level
被設(shè)置為replica
或更高, archive_mode
設(shè)置為on
,并且設(shè)置一個archive_command
,該命令只當(dāng)一個
開關(guān)文件
存在時執(zhí)行歸檔。例如:
archive_command = 'test ! -f /var/lib/pgsql/backup_in_progress || (test ! -f /var/lib/pgsql/archive/%f && cp %p /var/lib/pgsql/archive/%f)'
該命令在/var/lib/pgsql/backup_in_progress
存在時執(zhí)行歸檔,否則會安靜地返回0值退出狀態(tài)(讓PostgreSQL能回收不需要的WAL文件)。
通過這樣的準(zhǔn)備,可以使用一個如下所示的腳本來建立備份:
touch /var/lib/pgsql/backup_in_progress
psql -c "select pg_start_backup('hot_backup');"
tar -cf /var/lib/pgsql/backup.tar /var/lib/pgsql/data/
psql -c "select pg_stop_backup();"
rm /var/lib/pgsql/backup_in_progress
tar -rf /var/lib/pgsql/backup.tar /var/lib/pgsql/archive/
開關(guān)文件/var/lib/pgsql/backup_in_progress
首先被創(chuàng)建,這使對于未完成WAL文件的歸檔操作發(fā)生。備份完成之后開關(guān)文件會被刪除。歸檔的WAL文件則被加入到備份中,這樣基礎(chǔ)備份和所有需要的WAL文件都是同一個tar文件的組成部分。請記住在你的備份腳本中加入錯誤處理。
如果擔(dān)心歸檔存儲的尺寸,你可以使用gzip來壓縮歸檔文件:
archive_command = 'gzip < %p > /var/lib/pgsql/archive/%f'
那么在恢復(fù)時你將需要使用gunzip:
restore_command = 'gunzip < /mnt/server/archivedir/%f > %p'
archive_command
腳本很多人選擇使用腳本來定義他們的archive_command
,這樣他們的postgresql.conf
項看起來非常簡單:
archive_command = 'local_backup_script.sh "%p" "%f"'
任何時候如果你希望在歸檔處理中使用多個命令,明智的方法是使用一個獨立的腳本文件。這可以使腳本更為復(fù)雜,它可以使用一種流行的腳本語言來編寫,例如bash或perl。
需要在一個腳本內(nèi)解決的需求例子包括:
將數(shù)據(jù)拷貝到安全的場外數(shù)據(jù)存儲
批處理WAL文件,這樣它們可以每三小時被傳輸一次,而不是一次一個
與其他備份和恢復(fù)軟件交互
與監(jiān)控軟件交互以報告錯誤
在使用一個archive_command
腳本時,最好啟用logging_collector。任何從該腳本被寫到stderr的消息將出現(xiàn)在數(shù)據(jù)庫服務(wù)器日志中,這允許在復(fù)雜配置失敗后能更容易被診斷。
在編寫此文檔時,連續(xù)歸檔技術(shù)存在一些限制。這可能會在未來的發(fā)布中被修復(fù):
如果一個CREATE DATABASE命令在基礎(chǔ)備份時被執(zhí)行,然后在基礎(chǔ)備份進(jìn)行時CREATE DATABASE
所復(fù)制的模板數(shù)據(jù)庫被修改,恢復(fù)中可能會導(dǎo)致這些修改也被傳播到已創(chuàng)建的數(shù)據(jù)庫中。這當(dāng)然是我們不希望的。為了避免這種風(fēng)險,最好不要在創(chuàng)建基礎(chǔ)備份時修改任何模板數(shù)據(jù)庫。
CREATE TABLESPACE命令會WAL以其字面絕對路徑記錄,并且因此將在重放時以相同的絕對路徑來創(chuàng)建表空間。當(dāng)日志在一臺不同的機器上被重放時,這可能也不是我們希望的。即使日志在同一臺機器上被重放也是危險的,就算是恢復(fù)到一個新的數(shù)據(jù)目錄重放過程也會覆蓋原來表空間的內(nèi)容。為了避免這種潛在的陷阱,最佳做法是在創(chuàng)建或丟棄表空間后創(chuàng)建一個新的基礎(chǔ)備份。
還需要注意的是,默認(rèn)的WAL格式相當(dāng)龐大,因為它包括了很多磁盤頁快照。這些頁快照被設(shè)計用于支持崩潰恢復(fù),因為我們可能需要修復(fù)斷裂的磁盤頁。依靠你的系統(tǒng)硬件和軟件,頁斷裂的風(fēng)險可能會小到可以忽略,在此種情況下你可以通過使用full_page_writes參數(shù)關(guān)閉頁快照來顯著降低歸檔日志的總?cè)萘浚ㄔ谶@樣做之前閱讀
第 29 章中的注解和警告)。關(guān)閉頁快照并不會阻止使用日志進(jìn)行PITR操作。一個未來的開發(fā)點是通過移除不需要的頁拷貝來壓縮歸檔的WAL數(shù)據(jù),即使full_page_writes
為on。同時,管理員可能希望通過盡可能增大檢查點間隔參數(shù)來減少WAL中包含的頁快照數(shù)量。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: