1. 程式人生 > 實用技巧 >PostgreSQL DBA快速入門(四) - 體系架構

PostgreSQL DBA快速入門(四) - 體系架構

>>> hot3.png

PostgreSQL在開源關係型資料庫市場是最先進的資料庫。他的第一個版本在1989年釋出,從那時開始,他得到了很多擴充套件。根據db-enginers上的排名情況,PostgreSQL目前在資料庫領域排名第四。

本篇部落格,我們來討論一下PostgreSQL的內部架構,以及各個元件之間如何互動。這將是本期PostgreSQL DBA系列部落格的基石。

一、PostgreSQL的架構

PostgreSQL的物理架構非常簡單,它由共享記憶體、一系列後臺程序和資料檔案組成。 (如下圖)

二、Shared Memory

共享記憶體是伺服器伺服器為資料庫快取和事務日誌快取預留的記憶體快取空間。其中最重要的組成部分是Shared Buffer和WAL Buffer。

Shared Buffer

Shared Buffer的目的是減少磁碟IO。為了達到這個目的,必須滿足以下規則:

  • 當需要快速訪問非常大的快取時(10G、100G等)
  • 如果有很多使用者同時使用快取,需要將內容儘量縮小
  • 頻繁訪問的磁碟塊必須長期放在快取中

WAL Buffer

WAL Buffer是用來臨時儲存資料庫變化的快取區域。儲存在WAL Buffer中的內容會根據提前定義好的時間點引數要求寫入到磁碟的WAL檔案中。在備份和恢復的場景下,WAL Buffer和WAL檔案是極其重要的。

三、PostgreSQL 程序型別

PostgreSQL有四種程序型別

  1. Postmaster (Daemon) Process(主後臺駐留程序)
  2. Background Process(後臺程序)
  3. Backend Process(後端程序)
  4. Client Process(客戶端程序)

Postmaster Process

主後臺駐留程序是PostgreSQL啟動時第一個啟動的程序。啟動時,他會執行恢復、初始化共享記憶體愛你的執行後臺程序操作。正常服役期間,當有客戶端發起連結請求時,它還負責建立後端程序。

如果通過pstree命令檢視程序之間的關係,你會發現Postmaster程序是其他所有程序的父程序。

Background Process

PostgreSQL操作需要的後臺程序列表如下:

程序作用
logger將錯誤資訊寫到log日誌中
checkpointer當檢查點出現時,將髒記憶體塊寫到資料檔案
writer週期性的將髒記憶體塊寫入檔案
wal writer將WAL快取寫入WAL檔案
Autovacuum launcher當自動vacuum被啟用時,用來派生autovacuum工作程序。autovacuum程序的作用是在需要時自動對膨脹表執行vacuum操作。
archiver在歸檔模式下時,複製WAL檔案到特定的路徑下。
stats collector用來收集資料庫統計資訊,例如會話執行資訊統計(使用pg_stat_activity檢視)和表使用資訊統計(pg_stat_all_tables檢視)

Backend Process

最大後臺連結數通過max_connections引數設定,預設值為100。後端程序用於處理前端使用者請求並返回結果。查詢執行時需要一些記憶體結構,就是所謂的本地記憶體(local memory)。本地記憶體涉及的主要引數有:

  1. work_mem:用於排序、點陣圖索引、雜湊連結和合並連結操作。預設值為4MB。
  2. maintenance_work_mem:用於vacuum和建立索引操作。預設值為64MB。
  3. temp_buffers:用於臨時表。預設值為8MB。

Client Process

客戶端程序需要和後端程序配合使用,處理每一個客戶連結。通常情況下,Postmaster程序會派生一個紫禁城用來處理使用者連結。

四、資料庫結構

想要理解PostgreSQL的資料庫結構,需要先了解一些重要的概念。

資料庫相關概念:

  1. PostgreSQL由一系列資料庫組成。一套PostgreSQL程式稱之為一個數據庫群集。
  2. 當initdb()命令執行後,template0 , template1 , 和postgres資料庫被建立。
  3. template0和template1資料庫是建立使用者資料庫時使用的模版資料庫,他們包含系統元資料表。
  4. initdb()剛完成後,template0和template1資料庫中的表是一樣的。但是template1資料庫可以根據使用者需要建立物件。
  5. 使用者資料庫是通過克隆template1資料庫來建立的;

表空間相關概念:

  1. initdb()後馬上建立pg_default和pg_global表空間。
  2. 建表時如果沒有指定特定的表空間,表預設被存在pg_default表空間中。
  3. 用於管理整個資料庫叢集的表預設被儲存在pg_global表空間中。
  4. pg_default表空間的物理位置為$PGDATA\base目錄。
  5. pg_global表空間的物理位置為$PGDATA\global目錄。
  6. 一個表空間可以被多個數據庫同時使用。此時,每一個數據庫都會在表空間路徑下建立為一個新的子路徑。
  7. 建立一個使用者表空間會在$PGDATA\pg_tblspc目錄下面建立一個軟連線,連線到表空間制定的目錄位置。

表相關概念:

  1. 每個表有三個資料檔案。
  2. 一個檔案用於儲存資料,檔名是表的OID。
  3. 一個檔案用於管理表的空閒空間,檔名是OID_fsm。
  4. 一個檔案用於管理表的塊是否可見,檔名是OID_vm。
  5. 索引沒有_vm檔案,只有OID和OID_fsm兩個檔案

其他需要注意的地方

表和索引建立時檔名是OID,此時的OID和pg_class.relfilenode的值是一樣的。不管怎樣,當我們執行重寫操作時(truncate,cluster,vacuum full,reindex等),被修改物件的relfilenode值也會被修改,檔名也會隨著reffilenode值一起改變。我們可以通過pg_relation_filepath('<object_name>')檢視很容易的檢查檔案位置和名稱。

五、執行測試

initdb()完成後,如果登入資料庫查詢檢視pg_database,我們可以看到template0 , template1和 postgres資料庫已經被建立好了。

  • 通過datistemplate列,我們可以看到template0和template1是使用者建立資料庫時使用的模版資料庫,其他的都不是模版資料庫。
  • 通過datlowconn列,可以看出該資料庫是否允許訪問。因為template0資料庫不能被訪問,所以該資料庫的內容不能被修改。
  • 設定兩個模版資料庫的原因是template0是初始狀態,而template1資料庫則是可以整合使用者某些需求的模版資料庫。
  • postgres資料庫時使用模版template1建立的預設資料庫,如果連結時不指定資料庫名稱,預設連線到postgres資料庫。
  • 資料庫儲存在$PGDATA\base目錄下。路徑的名稱和資料庫OID的名稱一致。

六、建立使用者資料庫

上文提過,使用者資料庫建立是通過克隆template1資料庫。為了驗證這個規則,我們現在template1中建立一個表t1,緊接著建立一個mydb01資料庫,檢查t1表是否在mydb01中存在。

pg_default tablespace

initdb()後,如果登入資料庫查詢pg_tablespace檢視,會發現pg_global和pg_default表空間已經建立好。

pg_default表空間的位置為$PGDATA\base。每一個數據庫都擁有一個以自己OID命令的子路徑。

pg_global表空間

pg_global表空間用於儲存叢集級別的資料。

  • 例如pg_開頭的表
  • pg_global表空間路徑為$PGDATA\global.

七、建立使用者表空間

pg_tablespace檢視顯示myts01表空間已經被建立好。

$PGDATA/pg_tblspc路徑下有一個符號連結指到目標目錄。

下面分別連線到postgres和mydb01資料庫,建立表。

如果檢視/data01路徑下的內容,會發現上面建立的兩個資料庫中的t1表,分別在下面有一個對應OID的資料夾存在。

修改表空間位置

PostgreSQL在建立表空間時指定一個特定的路徑。因此,如果該特定路徑已經滿了,資料就不能在向裡面儲存了。為了解決該問題,我們可以使用磁碟管理程式擴充套件空間。但是如果不想使用磁碟管理程式,我們可以通過該表表空間的位置來解決該問題。命令如下:

八、Vacuum是什麼?

vacuum執行如下操作:

  1. 收集表和索引的統計資訊
  2. 整理表
  3. 清理表和索引中的死亡塊
  4. 被XID凍結,防止XID迴繞

#1 和 #2 是資料庫管理需要的。#3 和 #4 PostgreSQL MVCC 特性的要求。

九、PostgreSQL和Oracle MySQL之間的區別

二者之間最大的不同是MVCC模型和共享池(shared pool)。

指標ORACLEPostgreSQL
MVCC模型UNDOStore previous
實現方法Segmentrecord within block
共享池existsit does not exist

MVCC模型的區別

為了增加併發,必須遵循“讀操作不阻塞寫操作,寫操作不阻塞讀操作”的原則。為了實現這個原則,多版本併發控制(MVCC)理論被引入。Oracle使用UNDO段實現MVCC。而PostgreSQL儲存之前的記錄在資料塊中,它通過事務XID和事務的xmin、xmax來控制事務版本。

Shared Pool

PostgreSQL不提供共享池。這對於熟悉Oracle的使用者來說有點尷尬。共享池是Oracle中最基本和最重要的元件。PostgreSQL在程序級別提供SQL資訊的共享能力,而不是共享池。換句話說,如果我們在同一個程序中多次執行相同的SQL,它只會硬解析一次。

非常感謝拜讀本篇部落格,下次再見~

轉載於:https://my.oschina.net/javacy/blog/1921664