PostgreSQL/架構
PostgreSQL 實現了一種 客戶端-伺服器架構。每個 客戶端程序 連線到伺服器端的單個 後端程序。
客戶端無法直接訪問資料庫檔案及其儲存的資料。相反,它們向 伺服器 傳送請求,並從那裡接收請求的資料。伺服器為每個客戶端連線啟動一個程序。這樣的後端程序透過操作 共享記憶體 處理客戶端的請求。這會導致 例項 的其他活動(檔案訪問、WAL、真空等)。例項是一組在公共共享記憶體上執行的伺服器端程序。PostgreSQL 不使用執行緒。
在啟動時,例項由一個名為 Postmaster 的單個程序啟動。它載入配置檔案,分配共享記憶體,並啟動例項的其他協作程序:後臺寫入器、檢查點、WAL 寫入器、WAL 歸檔器、自動真空、統計收集器、日誌記錄器 等等。隨後,Postmaster 監聽其配置的系統埠。響應新的客戶端連線嘗試,它啟動新的後端程序,並將身份驗證、通訊和所有後續請求的處理委託給它們。下圖可視化了 RAM、程序、檔案及其協作的主要方面。

像 SELECT 或 UPDATE 這樣的客戶端請求通常會導致讀取或寫入資料的必要性。這是由客戶端的後端程序執行的。這種 I/O 活動 **不會直接在磁碟上完成**。相反,它們在共享記憶體中的快取中完成,該快取映象檔案頁面。訪問此類快取比訪問磁碟快得多。讀取訪問僅影響快取,而寫入訪問是透過寫入日誌來完成的,即所謂的預寫日誌或 WAL。
共享記憶體的大小有限,可能需要清除頁面。只要此類頁面的內容沒有改變,這就不成問題。但它們可能會被修改。修改後的頁面稱為髒頁面(或髒緩衝區),在清除它們之前,必須將它們寫回磁碟。後臺寫入器程序和檢查點負責此操作。它們確保快取在短時間延遲後與檔案同步。從 RAM 到磁碟的同步包括兩個步驟。
首先,每當頁面的內容發生變化時,都會建立一個 WAL 記錄,其中包含增量資訊(舊內容和新內容之間的差異)並存儲在共享記憶體的另一個區域中。在 COMMIT 或更早之前,WAL 寫入器程序讀取它們並將它們追加到當前 WAL 檔案的末尾。這種順序寫入比寫入堆檔案和索引檔案的隨機位置快。在將髒頁面本身傳輸到磁碟的第二步之前,必須將來自一個髒頁面的所有 WAL 記錄傳輸到磁碟。
其次,後臺寫入器程序將髒緩衝區從共享記憶體傳輸到檔案。由於 I/O 活動可能會阻塞其他程序,因此它會定期啟動,並且只執行一小段時間。這樣做,其廣泛的(也是昂貴的)I/O 活動分散在一段時間內,避免了令人衰弱的 I/O 峰值。檢查點程序也將髒緩衝區傳輸到檔案。
檢查點程序透過寫入和重新整理所有較舊的髒緩衝區、所有較舊的 WAL 記錄以及最終將特殊的檢查點記錄寫入磁碟來建立 檢查點。因此,檢查點是事務序列中的一點,在該點保證堆檔案和索引檔案已使用該檢查點之前的 tất cả các trang bẩn được cập nhật。
WAL 檔案包含對資料的更改。這種“增量資訊”在系統崩潰的情況下用於恢復(資料庫備份 + WAL 檔案 --> 崩潰之前的資料庫)。因此,WAL 檔案應被複制並儲存在安全的地方,直到下一次資料庫備份完成。這是 WAL 歸檔器程序的職責。可以配置它執行一個指令碼,只要 WAL 檔案已滿並切換到下一個檔案,該指令碼就會複製 WAL 檔案。當然,出於安全原因,此類副本應完成到單獨的磁碟或伺服器。但將原始 WAL 檔案儲存在與堆檔案和索引檔案不同的磁碟上也是一個好主意。這種分離提高了效能。這可以透過使用指向不同磁碟上的目錄的符號連結來實現。
自動真空程序將堆和索引檔案中的不再被任何事務使用的舊記錄版本標記為“最終刪除”。因此,它釋放了它們佔用的空間以供重用。需要這種程序是由於 MVCC 架構造成的。
統計收集器收集有關對 SQL 物件(如表、行、索引、頁面等)的訪問量的計數器,並將它們儲存在系統表中。
日誌記錄器將有關在資料庫訪問期間可能發生的或多或少嚴重事件(例如,錯誤密碼、無許可權、長時間執行的查詢等)的文字行寫入順序檔案。