書不是拿來相信的,而是拿來探究的。

— 安伯托·艾可(Umberto Eco),《玫瑰的名字》

這本書寫給誰#

本書寫給那些不願意把資料庫當成黑盒子的人。如果你樂於追根究柢、不習慣把專家建議照單全收、想親自把每件事弄清楚,那麼這本書適合你。

作者假設讀者具備以下條件:

  • 已經實際用過 PostgreSQL,對它的運作方式有大致概念
  • 不需要教學如何安裝伺服器、輸入 psql 指令或設定組態參數

入門使用者可能會覺得內容偏難。另一方面,若你熟悉其他資料庫系統、正要轉換到 PostgreSQL 並想理解兩者差異,本書同樣適用。作者自陳:幾年前若有這樣一本書,能替他省下大量時間——這正是他最終寫下它的原因。

這本書不提供什麼#

  • 不是食譜集:不會給你每種場合的現成解法。但只要理解複雜系統的內部機制,你就能分析、批判性地評估他人經驗,並得出自己的結論。正因如此,作者會解釋一些乍看毫無實用價值的細節。
  • 不是教學手冊:對作者本人較感興趣的領域挖得很深,其他領域則可能隻字未提。
  • 不是參考文件:作者力求精確,但無意取代官方文件,可能略去他認為不重要的細節。任何不清楚的情況,請查閱文件。
  • 不教你開發 PostgreSQL 核心:不預設讀者懂 C 語言,主要對象是資料庫管理者(DBA)與應用程式開發者。但書中提供大量原始碼指引,讓你想挖多深都可以。

這本書提供什麼#

導論章節簡要帶過後續敘事所依賴的主要資料庫概念。作者不期待讀者從中獲得太多新資訊,收錄它是為了讓整體圖像完整,同時也方便從其他資料庫系統遷移過來的讀者。

篇章主題涵蓋內容
Part I隔離與 MVCC先從使用者視角談有哪些隔離層級及其影響,再深入內部;涵蓋多版本並行控制(multiversion concurrency control, MVCC)與快照隔離(snapshot isolation)的實作細節,特別著重過期列版本的清理
Part II緩衝快取與 WAL緩衝快取,以及故障後用來還原資料一致性的預寫式日誌(write-ahead log, WAL)
Part III各類鎖的結構與用法:WAL 用的輕量鎖、關聯層級的重量鎖、列層級鎖
Part IV查詢執行伺服器如何規劃並執行 SQL 查詢;可用的資料存取方法、連接方法,以及統計資訊如何被運用
Part V索引類型從已涵蓋的 B-tree 延伸到其他存取方法;說明界定索引系統核心、索引存取方法與資料型別之間邊界的可擴充性原則(並由此帶出運算子類別的概念),再逐一深入各方法

PostgreSQL 內建多個「內省」(introspective)擴充模組,日常工作用不到,卻能讓我們窺看伺服器的內部行為。本書大量使用這類擴充——它們除了幫助探索內部機制,在複雜使用情境的問題排查上也很有幫助。

閱讀慣例#

本書力求可以從頭到尾逐頁閱讀,但不可能一次揭露所有真相,因此同一主題會多次回訪。為避免反覆寫「後面會再談」而拉長篇幅,作者改用頁邊頁碼標註交叉引用:向前的頁碼指向後續討論,向後的頁碼指向先前已提及之處。

  • 版本標註:本文與所有程式碼範例皆適用於 PostgreSQL 14。某些段落旁的頁邊會標示版本號,表示該資訊從指定版本起才成立——更早的版本要不是沒有該功能,就是採用不同實作。這對尚未升級到最新版本的讀者很有用。
  • 參數預設值:頁邊也用來標示所討論參數的預設值。一般參數與儲存參數的名稱以斜體印出,例如 work_mem
  • 側註:可能讓討論岔題、但作者忍不住收錄的內容,會以特殊格式印出,方便略過。
程式碼與範例的呈現方式

程式碼以 => 作為提示符號,必要時附上伺服器回應:

=> SELECT now();
              now
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
 20230306 14:00:08.008545+03
(1 row)

只要在 PostgreSQL 14 上仔細重現書中所有指令,你應該會得到完全相同的結果(連交易 ID 之類的無關細節都一樣)。書中所有程式碼範例都是由包含這些指令的腳本產生的。

需要說明多個交易並行執行時,另一個 session 中執行的程式碼會縮排並以垂直線標示

    => SHOW server_version;
     server_version
    −−−−−−−−−−−−−−−−
     14.7
    (1 row)

要試跑這類指令(對自學或任何實驗都很有幫助),開兩個 psql 終端機會很方便。

指令名稱與各種資料庫物件(表格、欄位、函式、擴充等)在文中以無襯線字體標示,例如 pg_class。若某工具是從作業系統呼叫,會以 $ 結尾的提示符號顯示:

postgres$ whoami
postgres

作者使用 Linux,但不涉及技術細節,具備基本認識即可。

資訊來源與致謝

資訊來源#

註腳中提供多個資訊來源連結,其中最重要的是:

  1. PostgreSQL 官方文件(postgresql.org/docs/14/index.html)——知識的泉源。它是專案不可或缺的一部分,由 PostgreSQL 開發者親自維護,永遠保持在最新狀態。
  2. 原始碼(git.postgresql.org)——毫無疑問是最主要的參考依據。令人驚訝的是,即使不懂 C,光是閱讀註解、瀏覽 README 檔案就能找到許多答案。
  3. Commitfest 條目(commitfest.postgresql.org)——可追溯所有變更的歷史;若願意翻遍 psql-hackers 郵件列表中成堆的信件,就能理解開發者決策背後的邏輯。

致謝#

一本書不可能獨力完成。作者感謝 Pavel Luzanov 在對的時機提議著手這件真正值得的事;感謝 Postgres Professional 讓他得以在業餘時間之外投入寫作,並特別感謝 Oleg Bartunov 分享想法與無盡的能量、Ivan Panchenko 的全力支持與 LaTeX 協助;感謝教育團隊同事的創作氛圍與討論,那些討論形塑了訓練課程的範圍與形式;感謝 Pavel Tolmachev 對草稿的細緻審閱。

本書許多章節最初發表於 Habr 部落格,讀者的意見與回饋顯示了這項工作的重要性、點出作者知識中的缺口,並幫助他改進文本。作者也感謝 Liudmila Mantrova 為本書語言所下的功夫,以及她將本書翻譯為英文。

書中提及的每一個函式或功能,都需要特定的人投入多年心血。作者欽佩 PostgreSQL 的開發者們,也很高興能有幸稱其中許多人為同事。