標籤:
在前面的章節中,我們已經理解了各種複製概念。這不僅僅是一個為了接下來將要介紹的東西而增強您的意識的理論概述,還將為您介紹大體的主題。
在本章,我們將更加接近實際的解決方案,並瞭解PostgreSQL內部是如何工作的,複製意味著什麼。我們將看到所謂的交易記錄(XLOG)做什麼,以及它是如何運作的。XLOG在PostgreSQL複製機制中起著主要作用。理解這部分是如何工作的是必要的。
2.1 PostgreSQL如何寫入資料
PostgreSQL的複製完全是關於寫入資料的。因此,PostgreSQL內部寫一個資料區塊是直接和複製,複製概念相聯絡及高度相關的。在本章中,我們將深入寫入操作。在本章您將學習如下東西:
• PostgreSQL如何寫入資料
•涉及到哪些記憶體和儲存參數
•寫入如何進行最佳化
•寫入如何被複製
•如何保證資料一致性
一旦您讀完本章,就為您理解下一章做好了準備,它將教會您如何安全地複製您的第一個資料庫。
2.1.1 PostgreSQL的磁碟布局
本章我們要瞭解的第一個問題就是PostgreSQL的磁碟布局。瞭解磁碟布局對檢查一個現有的安裝是非常有協助的,對設計一個高效率,高效能的安裝也是很有協助的。
與其他資料庫系統相比,如Oracle,PostgreSQL依靠檔案系統來儲存資料。PostgreSQL不使用原始裝置。這背後的哲學是如果一個檔案系統的開發人員很好地完成了他或她的工作,就沒有必要一遍又一遍地重新實現檔案系統的功能。
查看資料目錄
為了理解PostgreSQL使用的檔案系統層,我們可以看一下在資料目錄(由initdb在安裝時建立)下我們能看到什麼:
[[email protected]]$ ls -l
total 92
-rw------- 1 hs staff 4 Feb 11 18:14 PG_VERSION
drwx------ 6 hs staff 4096 Feb 11 18:14 base
drwx------ 2 hs staff 4096 Feb 11 18:14 global
drwx------ 2 hs staff 4096 Feb 11 18:14 pg_clog
-rw------- 1 hs staff 4458 Feb 11 18:14 pg_hba.conf
-rw------- 1 hs staff 1636 Feb 11 18:14 pg_ident.conf
drwx------ 4 hs staff 4096 Feb 11 18:14 pg_multixact
drwx------ 2 hs staff 4096 Feb 11 18:14 pg_notify
drwx------ 2 hs staff 4096 Feb 11 18:14 pg_serial
drwx------ 2 hs staff 4096 Feb 11 18:14 pg_snapshots
drwx------ 2 hs staff 4096 Feb 11 18:19 pg_stat_tmp
drwx------ 2 hs staff 4096 Feb 11 18:14 pg_subtrans
drwx------ 2 hs staff 4096 Feb 11 18:14 pg_tblspc
drwx------ 2 hs staff 4096 Feb 11 18:14 pg_twophase
drwx------ 3 hs staff 4096 Feb 11 18:14 pg_XLOG
-rw------- 1 hs staff 19630 Feb 11 18:14 postgresql.conf
-rw------- 1 hs staff 47 Feb 11 18:14 postmaster.opts
-rw------- 1 hs staff 69 Feb 11 18:14 postmaster.pid
您會看到一系列的檔案和目錄,這都是運行一個資料庫執行個體的所需要的。讓我們看看其中的細節。
PG_VERSION-PostgreSQL的版本號碼
在啟動時該檔案會告訴檔案系統,資料目錄是否包含正確的版本號碼。請注意:只有主要版本號在這個檔案中。在同一個主要版本下的兩個不同的小版本之間進行複製是可能的,也是容易的。
[[email protected]]$ cat PG_VERSION
9.2
該檔案是可讀的純文字。
base-實際資料目錄
在資料目錄中,base目錄是最重要的目錄之一。他實際上包含了真實資料(系統資料表,索引等)。在base目錄內部,每個資料庫有它自己的子目錄:
[[email protected] base]$ ls -l
total 24
drwx------ 2 hs staff 12288 Feb 11 18:14 1
drwx------ 2 hs staff 4096 Feb 11 18:14 12865
drwx------ 2 hs staff 4096 Feb 11 18:14 12870
drwx------ 2 hs staff 4096 Feb 11 18:14 16384
我們可以很容易地把這些目錄串連到我系統內的資料庫,值得注意的是PostgreSQL使用資料庫的對象ID。這和使用名稱相比有許多優勢,因為對象ID從來不會改變,並且為抽象各種問題提供一個好的方法,例如在伺服器上使
用不同的字元集的問題等等。
test=# SELECT oid, datname FROM pg_database;
oid |datname
-------+-----------
1 | template1
12865 | template0
12870 | postgres
16384 | test
(4 rows)
現在,我們可以看到資料在這些特殊的資料庫目錄內是如何儲存的。在PostgreSQL中,每個表關係到(至少)一個資料檔案。讓我建立一個表,看看會發生什麼:
test=# CREATE TABLE t_test (idint4);
CREATE TABLE
我們可以檢查系統資料表來擷取所謂的relfilenode,這代表磁碟上的隱藏檔名稱:
test=# SELECT relfilenode, relname
FROM pg_class
WHERE relname = ‘t_test‘;
relfilenode | relname
-------------+---------
16385 | t_test
(1 row)
一旦表被建立,PostgreSQL就會在磁碟上建立一個空檔案:
[[email protected] base]$ ls -l 16384/16385*
-rw------- 1 hs staff 0Feb 12 12:06 16384/16385
越來越多的資料檔案
表有時候會相當大,因此,把一個表的所有相關的資料都放到單個檔案或多或少是不可能的。為瞭解決這個問題,每添加1GB的資料PostgreSQL就會額外添加一個檔案。
因此,如果一個叫16385的檔案大小超過1GB,就會有一個叫16385.1的檔案。一旦這個檔案被填滿,您就會看到一個名為16385.2的檔案,等等。通過這種方式,在某些罕見的作業系統或嵌入式裝置上,PostgreSQL中的表可以安全可靠地擴大規模,而不必擔心低層檔案系統限制。
在塊中執行I/O
為了提高I/O效能,PostgreSQL總是以8k大小的塊執行I/O.因此,您會看到您的資料檔案總是以8k的步長增長。當談到物理複製,您必須確保雙方(master 和slave)都用相同的塊大小進行編譯。
[除非您明確地按您自己使用的不同的塊大小來編譯PostgreSQL,您可以一直接受資料區塊一致且準確的8k大小的事實。]
關係forks
除了在前面段落討論的資料檔案之外,PostgreSQL會實行相同的檔案號建立額外的檔案。截至目前,這些檔案用來儲存表(FreeSpaceMap)內部空閑空間資訊,所謂的VisibilityMap等等。以後,將會有更多類型的關係forks可能被添加進來。
global-全域資料
global包含全域系統資料表。這個目錄較小,您不應該期望會有過多的儲存消耗。
處理獨立的資料檔案
使用者經常忘記一件事情:單個PostgreSQL資料檔案基本上沒有多少價值。如果您只有一個資料檔案,不可能可靠地儲存資料;容易地試圖提取單個檔案中的資料是毫無希望的猜測。因此,為了讀資料,您需要一個完整的執行個體。
pg_clog-提交日誌
提交日誌是一個工作資料庫執行個體的一個重要組成部分。它儲存系統上進行的事務的狀態。一個事務有四種狀態(TRANSACTION_STATUS_IN_PROGRESS,TRANSACTION_STATUS_COMMITTED,
TRANSACTION_STATUS_ABORTED, andTRANSACTION_STATUS_SUB_COMMITTED),如果一個事物的提交日誌的狀態是不可用,PostgreSQL將不知道是否應該被看到。
如果一個資料庫執行個體的提交日誌由於某種原因被破壞(也許是因為檔案系統損壞),您可以提前一些有趣的時間。
[如果提交日誌被損壞,我們建議給和資料庫執行個體(檔案系統)做快照,偽造提交日誌,它有時有助於從有問題的資料庫執行個體獲得一個合理數量的資料。]
pg_hba.conf-基於主機的網路設定
pg_hba.conf檔案配置PostgreSQL的內部防火牆,代表了一個PostgreSQL叢集中的兩個最重要的設定檔之一。它允許使用者定義任何基於請求來源的各種認證的類型。一個資料庫管理員,瞭解pg_hba.conf檔案是至關重要的,因為這個檔案決定是否允許一個slave串連到master。如果您碰巧錯過了這裡的東西。您可能會在slave的日誌中看到錯誤資訊(例如:沒有pg_hba.conf的許可…)
pg_ident.conf-身份認證
pg_ident.conf檔案可和pg_hba.conf檔案結合用於配置身份認證。
pg_multixact-多事務狀態資料
多事物日誌管理器可以有效地處理共用行鎖。此目錄中和複製相關的東西沒有實際的影響。
pg_notify-監聽/通知數據
在這個目錄中,系統儲存關於監聽/通知的資訊(非同步後端介面)。和複製沒有實際的影響。
pg_serial-關於提交序列化事務的資訊
序列化事務的資訊儲存在這裡。我們必須在磁碟上儲存序列化事務提交資訊,以確保長時間啟動並執行事務不會膨脹記憶體。內部採用一個簡單的SLRU結構來跟蹤這些事務。
pg_snapshot-輸出快照
這是一個由PostgreSQL快照管理需要的資訊組成的檔案。
在某些情況下,快照必須輸出到磁碟,以避免進入記憶體。崩潰之後,那些快照將自動被清理。
pg_stat_tmp-臨時統計資料
臨時統計資料存放區在這個檔案中。該資訊被大多數pg_stat_*系統檢視表所需要(因此,也為低層函數提供未經處理資料)。
pg_subtrans-子交易資料
在這個目錄中,我們儲存有關子事務的資訊。pg_subtrans(和pg_clog)目錄永久性的(在磁碟上)儲存事務相關資訊。有一定限制數目的記憶體葉儲存在記憶體中,因此,在很多情況下,沒有必要實際從磁碟讀取。但是如果有一個長期啟動並執行事務或一個開啟的在後端閑置的事務,從磁碟讀寫該資訊可能是必要的。它們也允許通過伺服器重啟確保資訊非揮發性儲存體。
pg_tblspc-到資料表空間的符號連結
pg_tblspc是一個非常重要的目錄。在PostgreSQL中,一個資料表空間是一個可以替代的儲存位置,由一個儲存資料的目錄來表示。
這裡最重要的是:如果一個資料庫執行個體被完全複製,我們不能簡單地依靠一個事實:叢集中的所有伺服器都使用同樣的磁碟布局和相同的儲存硬體。這裡儲存這樣一個情境:一個master比一個slave需要更多的I/O能力,這個slave可能只是身邊充當備份或備用的。為了讓使用者處理不同的磁碟布局,PostgreSQL將把符號連結到pg_tblspc關聯目錄。該資料庫將盲目地追隨那些符號連結找到這些資料表空間,無論它們在哪裡。
這為終端使用者提供了巨大的力量和靈活性。一般而言,控制儲存對複製以及效能都是必要的。請記住,這些符號連結只能事後變更。應該仔細考慮。
(我們建議使用僅在本節所描述的策略當他真正需要的時候。對於大多數的設定,在master和slave上絕對推薦使用相同的檔案系統布局。這樣可以大大減少複雜性。)
pg_twophase – 有關預先處理語句的資訊
PostgreSQL必須儲存有關兩階段交易認可的資訊。儘管兩階段交易認可是一個重要的特徵,該目錄本身對普通的系統管理員來說不太重要。
pg_XLOG – PostgreSQL 的交易記錄(WAL)
PostgreSQL事物日誌是本章我們必須要討論的基本目錄。pg_XLOG包含所謂XLOG的所有檔案。如果在過去的時間裡您有使用PostgreSQL,您可能熟悉術語WAL(WriteAhead Log)。XLOG和WAL是一個事物的兩個名字。對交易記錄也同樣適用。這三個術語被廣泛地應用,知道他們是一樣的意思是非常重要的。
pg_XLOG目錄一般是這樣的:
[[email protected]_XLOG]$ ls -l
total 81924
-rw------- 1 hs staff 16777216 Feb 12 16:29
000000010000000000000001
-rw------- 1 hs staff 16777216 Feb 12 16:29
000000010000000000000002
-rw------- 1 hs staff 16777216 Feb 12 16:29
000000010000000000000003
-rw------- 1 hs staff 16777216 Feb 12 16:29
000000010000000000000004
-rw------- 1 hs staff 16777216 Feb 12 16:29
000000010000000000000005
drwx------ 2 hs staff 4096 Feb 11 18:14 archive_status
您看到的是一堆檔案,它們總是16MB的大小(預設設定)一個XLOG檔案的檔案名稱通常是24個位元組長。編號總是十六進位。因此,該系統會計算”9,A,B,C,D,E,F,10”等等。
一個重要的事情是pg_XLOG目錄的大小不會瘋狂地隨著時間的推移而變大,它完全獨立於您在您系統上啟動並執行事務的類型。XLOG的大小由將在本章的後面進行討論的postgresql.conf中的參數決定的,簡而言之:無論您是運行小事務或者大事務,XLOG的大小都是一樣的。您可以輕鬆地運行一個像1TB一樣大的事務,只有極少數的XLOG檔案。這可能不是太有效,明智的效能,但它在技術上完全可行。
postgresql.conf – PostgreSQL設定檔的核心檔案
最後,還有一個主要的PostgreSQL設定檔。所有的配置參數都可以在postgresql.conf中被改變,我們將使用這個檔案廣泛設定複製和調整我們的資料庫執行個體,以確保我們的複製設定為我們提供了卓越的效能。
[如果您碰巧使用先行編譯的二進位檔案,可能無法在您的資料目錄找到postgresql.conf。它可能位於/etc/(在Linux/Unix)下的一些子目錄,或在您在Windows下選擇的地方。精確的位置是高度依賴於您正在使用的作業系統。資料目錄的典型的位置是/var/lib/pgsql/data。但是postgresql.conf往往在/etc/postgresql/9.X/main/postgresql.conf下(如在Ubuntu和類似系統)或直接在/etc/目錄下面。]
2.1.2 寫入一行資料
既然我們已經瞭解了磁碟布局,我們將進一步深入PostgreSQL和探究當PostgreSQL寫一行資料的時候會發生什麼。一旦您掌握了這一章,您會充分理解XLOG背後的概念。
需要注意的是,在關於寫一行資料的這一章,我們已經簡化了一些過程,以確保我們可以強調重點和PostgreSQL XLOG背後的思想。
一條簡單的INSERT語句
讓我們假設我們正在做類似下面的一個簡單的INSERT語句:
INSERT INTO foo VALUES (‘abcd‘):
正如人們所想象的,一個INSERT操作的目標是給現有的表添加一行資料。在前面關於PostgreSQL磁碟布局的章節中我們已經看到了,每個表將與磁碟上的一個檔案關聯。
讓我們進行一個心理實驗,假設這裡我們正在處理的表大小為10TB。PostgreSQL將看到INSERT操作並尋找這個表(使用現有的塊或者添加一個新塊)內的一些空餘的地方。為了這個例子的目的,我們簡單地把資料插入到表中的第二塊。
只要伺服器實際地儲存了事務,一切都沒有問題。如果有人在寫了abc而不是整個資料之後,拔了塞子,會發生什麼事情?當伺服器重新啟動以後,我們會發現我們處於一種狀況,我們有一個不完整的記錄塊,更有趣的是,我們甚至可能不會有絲毫的想法,這個塊包含的壞記錄可能在哪裡。
一般情況下,包含不完整的未知位置的行的表被認為是壞表。當然,系統資料表損壞不是什麼事,PostgreSQL社區會容忍的,特別地,沒有由於明顯的設計失誤引起的類似這樣的問題。
在WAL-writing期間崩潰
[我們必須確保PostgreSQL在任何給定的時間點的中斷中倖存,並且沒有資料丟失或者損壞。保護您的資料是好的,並且是絕對必須的。]
為瞭解決我們剛才討論過的問題,PostgreSQL使用了所謂的WAL(Write Ahead Log)或者簡單地XLOG。使用WAL意味著寫日誌在寫資料之前。因此,在我們實際把資料寫到表中之前,我們將按順序排列日誌條目,這表明我們將要計劃對我們的表做什麼。顯示了事情是如果工作的:
正如我們可以看到了,一旦我們將資料寫入到日誌(1),我們就可以把事務標記為完成(2)。之後,資料被寫到表中(3)。
[我們已經排除了等式中的記憶體部分—這將在本節稍後討論。]
讓我們用兩個例子說明這種方法的優點:
為了確保本章中介紹的概念堅如磐石的工作,我們必須確保我們能夠在任何時間點崩潰,而不用擔心我們的資料。讓我們假設,我們在寫XLOG時崩潰。這種情況下會發生什麼呢?在這種情況下,終端使用者將知道事務沒有成功,那麼,他或者她將不依賴事務的成功。
只要PostgreSQL啟動,它可以通過XLOG並重放一切要確保PostgreSQL是處於一致狀態的事情。所以,如果我們不通過WAL-writing來實現它,討厭的事情就已經發生了,我們不能指望有一個寫是成功的。
WAL條目將永遠知道它是否完成了。每個WAL條目都有一個內部校正和,因此,一旦有人試圖重放壞的WAL,PostgreSQL可以立即檢測到。在崩潰時,當我們可能無法依靠寫入到磁碟的最新資料時,這尤其重要。WAL將自動解決崩潰恢複中的這些問題。
[如果PostgreSQL配置正確,崩潰在任何時間點都是相當安全的。]
在WAL-writing之後崩潰
現在讓我們假設,我們已經成功通過了WAL-writing,之後我們馬上崩潰了,也許在寫底層表。如果我們只設法寫了ab而不是整個資料將會怎麼樣呢?
那麼,在這種情況下,我們將知道在重放期間丟失了什麼。再次,我們去重放日誌以確保在我們的資料表中的所有資料安全需要的是什麼。
雖然崩潰之後在一個表中找資料可能很困難,我們總能依靠一個事實,我們可以在WAL中找到資料。WAL是連續的,如果我們只是跟蹤資料寫了多遠,我們總能從那裡繼續進行;XLOG將直接引導我們到表中的資料,並且它總能知道哪裡有一個變化或者應該在哪裡做一個改變。PostgreSQL 沒有必要在WAL中搜尋資料;它只是從正確的角度將其重放。
[一旦一個事務完成了寫WAL,它不會再很容易就丟失了。]
2.1.3 讀一致性
既然我們已經看到了一個簡單的寫是如何執行的,我們必須看看寫對讀有什麼影響。接下來的圖片顯示了PostgreSQL資料庫系統的基本架構:
為了簡單起見,我們可以把一個資料庫執行個體看作一個由三個主要部分組成的東西:
1. PostgreSQL 資料檔案
2. 交易記錄
3. 共用快取
在前面的章節中,我們已經討論了資料檔案。您也看到了一些關於交易記錄本身的基本資料。現在我們要擴大我們的模型,並給這個架構圖添加另一個部分:遊戲的記憶體部分,所謂的共用緩衝區。
共用緩衝區的目的
共用緩衝區是PostgreSQL的I/O緩衝。它有助於緩衝8K的塊,這都是從作業系統中讀取的,它有助於保持寫回到磁碟以最佳化效率(稍後將在本章討論這是如何工作的)。
[共用緩衝區是很重的,因為它影響效能。]
但是,當說到共用快取時,效能並不是我們應該關注的唯一的問題。讓我們假設我們要發送一個查詢。為了簡單起見,我們也假設我們只需要一個塊來處理這個讀請求。如果我們做一個簡單的查詢將怎麼樣呢?也許我們正在尋找一些簡單的東西,像電話號碼,或者給定一個特定鍵的使用者名稱。下面的列表顯示,用大量簡化的方式,在所做的假設的情況下,PostgreSQL將做什麼,執行個體剛才已經重新啟動了:
1. PostgreSQL 將在快取(如前所述,這是共用緩衝區)中尋找所需要的塊。在一個剛剛啟動的執行個體的緩衝中,它是不會找到資料區塊的。
2. PostgreSQL 將向作業系統請求那個資料區塊。
3. 一旦資料被從作業系統載入了,PostgreSQL將把它放進第一個緩衝隊列中。
4. 已成功送達該查詢。
讓我們假設一個相同的塊將被第二個查詢再次使用。在這種情況下,事情將如下工作:
• PostgreSQL 將尋找所需要的資料區塊並且快取命中。
• PostgreSQL 會發現一個緩衝塊已經被重新使用了並把它從一個低層級的緩衝(Q1)移動到一個較進階別的緩衝(Q2)。在第二個隊列中的塊將在緩衝中保留的時間更長,因為它們證明比那些只在Q1層級的塊更重要。
[共用緩衝區應該有多大?在Linux下,8GB的是通常推薦的。在Windows下,低於1GB的值被證明是有用的(如PostgreSQL9.2)。從PostgreSQL9.3開始,在Windows下,更高的值可能是有益且可行的。在Linux下,瘋狂的大的共用緩衝區實際上是逆最佳化的。當然,這隻是一個經驗法則,特殊的安裝可能需要不同的設定。]
混合讀寫
請記住,在本節,全部都是關於理解寫,以確保我們的最終目標,全面深入理解複製,可以實現。因此,我們必須看看讀和寫是如何走到一起的。讓我們看看讀和寫如何走到一起的:
1. 一個寫請求到來。
2. PostgreSQL 將寫入交易記錄以確保可以達到一致性。
3. PostgreSQL 將擷取一個在PostgreSQL共用緩衝區內部的塊,並在記憶體中做出改變。
4. 一個讀請求到來。
5. PostgreSQL 將查詢快取並尋找所需要的資料。
6. 一個快取命中將著陸並且查詢將被送達。
這個例子的重點是什嗎?好吧,正如您可能已經注意到的,我們從來沒有討論實際的表下面的寫。我們討論了到快取的寫,到XLOG的寫,等等,但是沒有關於真正的資料檔案的寫。
[在這個例子中,我們在表裡所寫的行在或者不在表裡,這是完全不相關的。原因很簡單:如果我們需要一個剛剛被修改的塊,我們永遠都不會從表下面獲得。]
理解在寫操作期間或者之後,資料通常不直接寫到資料檔案是很重要的。稍後把資料寫出來對提高效率是有意義的。之所以這樣的原因是,它對複製有微妙的影響。資料檔案本身是毫無價值的,因為它既不一定完整又不一定正確。要運行一個PostgreSQL執行個體,您將總是需要資料檔案伴隨著交易記錄。否則,就沒有辦法倖免於崩潰。
從一致性的角度來看,共用緩衝區是在這裡完成使用者的資料的視圖。如果有什麼東西沒有在表中,邏輯上,它應該在記憶體中。
在崩潰的情況下,記憶體將丟失,所以XLOG被諮詢並重放,以再次將資料檔案轉換為一個一致的資料儲存。在任何情況下,資料檔案都只是故事一半。
[在PostgreSQL9.2以及之前的版本中,共用緩衝區只在SysV/POSIX 共用記憶體或者在Windows的類比SysV中。PostgreSQL9.3(在寫作的時候,未發布)開始使用記憶體對應檔,這在Windows下更快,在效能方面與在Linux下沒有區別,但是在BSDs下稍慢。BSD開發人員們已經開始解決這個問題。使用mmap可以使配置更容易,因為mmap是不受作業系統的限制的,只要有足夠的記憶體,它是沒有限制的。SysVshmem 是有限制的,大量的SysVshmem通常只有作業系統做相應的調整才被分配。從Linux發行版到Linux發行版,共用記憶體變數是預設配置的。Suse更趨於替代,而RedHat,Ubantu和一些其它的則更趨於保守。]
原文地址:http://www.cnblogs.com/songyuejie/p/4743316.html
PostgreSQL Replication之第二章 理解PostgreSQL的交易記錄(1)