中秋節假期這么快就沒了,這幾天還一直下雨,索性在家看看書。這次看的是Tom Lane的《A Tour of PostgreSQL Internals》。這篇小隨筆就算做學習筆記了。園子里面大神多,如果有哪里講得不對,還請各位前輩多多指教了~
在這個ppt里面,大神Tom Lane分別從三個角度對Postgresql的內部原理進行了介紹。
View 1 Postgresql進程以及內部進程間的通信
這部分比較簡短,主要介紹了客戶端/服務器間通信,服務器內部的通信。
1. 客戶端/服務器間通信
一圖勝千言,我們先上圖
將上圖一分為二地看,分為客戶端和服務器端:
1.1 客戶端
在客戶端中,主要有兩類進程,一個是客戶端本身的應用程序(Client Application),例如:psql,這些程序向服務器端發送DB請求或者接受從服務器端返回的查詢結果;
另一類是客戶端接口庫,主要用於處理前后端通信協議。它們是一組通信協議接口庫:libpq, ODBC, JDBC,Perl DBD等等。值得一提的是,libpq是Postgresql提供的使用C語言實現的協議處理庫。利用這個庫可以比較輕松地和后端進行通信。除了C以外,還支持Perl和PHP等其他語言,這些語言在內部也調用了libpq。(PSQLODBC在版本09.05.0400后完全使用libpq進行前后端的通信),當然,也有不依賴於libpq而直接與PostgreSQL通信的庫。比較具有代表性的是Java, PostgreSQL的JDBC驅動是不依賴於libpq直接與PostgreSQL通信的。
1.2 服務器端
1.2.1 postmaster進程
在服務器端,postmaster是管理后端的常駐進程,默認監聽UNIX Domain Socket和TCP/IP的5432端口,等待來自前端的的連接處理。一旦有前端連接過來,postgres會通過fork(2)生成子進程。對於沒有fork(2)的windows平台,則利用createProcess()生成新的進程。在這種情形下,父進程的數據不會被繼承過來,所以需要利用共享內存把父進程的數據繼承過來。
1.2.2 postgres進程
Postgres會接受前端過來的查詢,然后對數據庫進行檢索,最后把結果返回(select)或者對數據庫進行更新(update,delete,set等)。更新的數據同時還會記錄在事務日志里面(PostgreSQL稱為WAL日志),這個主要是當停電的時候,服務器當機,重新啟動的時候進行恢復處理的時候使用的。另外,把日志歸檔保存起來,可在需要進行恢復的時候使用。在PostgreSQL 9.0以后,通過把WAL日志傳送其他的postgreSQL,可以實時得進行數據庫復制,這就是所謂的‘數據庫復制’功能。
1.2.3 其他進程
在服務端除了以上兩個進程以外,還有其他很多輔助進程,這些進程都是由postmaster進程啟動的。
a) Writer process
Writer process在適當的時間點把共享內存上的緩存寫往磁盤。通過這個進程,可以防止在檢查點的時候(checkpoint),大量的往磁盤寫而導致性能惡化,使得服務器可以保持比較穩定的性能。Background writer起來以后就一直常駐內存,但是並非一直在工作,它會在工作一段時間后進行休眠,休眠的時間間隔通過postgresql.conf里面的參數bgwriter_delay設置,默認是200微秒。
這個進程的另外一個重要的功能是定期執行檢查點(checkpoint)。在檢查點的時候,會把共享內存上的緩存內容往數據庫文件寫,使得內存和文件的狀態一致。這樣可以在系統崩潰的時候可以縮短從WAL恢復的時間,另外也可以防止WAL無限的增長。 可以通過postgresql.conf的checkpoint_segments、checkpoint_timeout指定執行檢查點的時間間隔。
b) WAL writer process
WAL writer process把共享內存上的WAL緩存在適當的時間點往磁盤寫.這樣可以減輕后端進程在寫自己的WAL緩存時的壓力,提高性能。另外,非同步提交設為true的時候,可以保證在一定的時間間隔內,把WAL緩存上的內容寫入WAL日志文件。
c) Archive process
Archive process把WAL日志轉移到歸檔日志里。如果保存了基礎備份以及歸檔日志,即使是在磁盤完全損壞的時候,也可以回復數據庫到最新的狀態。
d) stats collector process
統計信息的收集進程。收集好統計表的訪問次數,磁盤的訪問次數等信息。收集到的信息除了能被autovaccum利用,還可以給其他數據庫管理員作為數據庫管理的參考信息。
e) Logger process
把postgresql的活動狀態寫到日志信息文件(並非事務日志),在指定的時間間隔里面,對日志文件進行rotate。
f) Autovacuum啟動進程
autovacuum launcher process是依賴於postmaster間接啟動vacuum進程。而其自身是不直接啟動自動vacuum進程的。通過這樣可以提高系統的可靠性。
g) 自動vacuum進程
autovacuum worker process進程實際執行vacuum的任務。有時候會同時啟動多個vacuum進程。
h) wal sender / wal receiver
wal sender 進程和wal receiver進程是實現postgresql復制(streaming replication)的進程。Wal sender進程通過網絡傳送WAL日志,而其他PostgreSQL實例的wal receiver進程則接收相應的日志。Wal receiver進程的宿主PostgreSQL(也稱為Standby)接受到WAL日志后,在自身的數據庫上還原,生成一個和發送端的PostgreSQL(也稱為Master)完全一樣的數據庫。
2. 服務器內部通信
還是要上圖:
postmaster在接受到客戶端的請求后,會創建共享內存,內存里的數據是從Unix系統硬盤里面讀出來的,供postgres進程讀取和寫入,即客戶端對postgresql數據庫中的數據的操作不是實時寫回物理磁盤的,而是通過Writer process定期寫回磁盤,這里具體可以參照上面提到的幾個進程。
為了能看得更明白一點,總結以上兩點,我們來一張更細致的圖,如下:
3. View 1 小結
postgresql進程間的這種機制的好處是:
- 客戶端和服務器端的“硬”分離,使系統具有良好的安全性和可靠性;
- 使得Postgrsql在網絡環境下能夠工作良好(此處應該是指客戶端接口庫);
- 在大部分Unix系統上使用方便,工作良好。
缺點也是明顯的:
- 服務器內部的通信過於依賴share memory(大小是有明顯限制的),限制了其擴展性;
- postgresql的連接啟動時間是一定的,對於運行時間較短的客戶端任務而言,該時間開銷所占比重較大。不過這個缺點通常可以通過客戶端連接池的方法來解決。
這篇介紹了 《A Tour of PostgreSQL Internals》中三個View中View 1 的內容,View2 和View3我們明天再繼續學習吧。
對了,附上鏈接,《A Tour of PostgreSQL Internals》
還有 本文也參考了Postgresql srcstructure