PostgreSQL 14 內部原理 封面

PostgreSQL 14 內部原理

👨‍💼: Egor Rogov
📅: March 8, 2023
Buy Now
📖:
寫給不願意把資料庫當黑盒子的人:從資料在磁碟上的組織方式、MVCC 與 WAL,一路拆解到鎖、查詢規劃與六種索引存取方法的內部實作。
📘 深度概覽

作者背景#

羅戈夫(Egor Rogov)任職於 Postgres Professional——一家專注於 PostgreSQL 的公司,也是俄語圈 PostgreSQL 生態的主要推動者之一——負責教育訓練體系,設計並講授該公司面向 DBA 與開發者的完整課程。

他的寫作動機直接來自這份工作。在前言中他自陳:幾年前若有這樣一本書,能替他省下大量時間,這正是他最終寫下它的原因。教學者的身分也解釋了本書最鮮明的特徵——它不是把原始碼翻譯成散文,而是把每一個機制拆成「可以自己動手驗證」的形式:幾乎每個論點後面都跟著一段可執行的 SQL,讓讀者用 pageinspectpg_visibility 這類擴充套件親眼看見頁面裡的位元組。他把書的最大價值明確定位在方法而非事實:「不論是這本書還是官方文件,都不該被視為理所當然。要思索、要實驗、要親手驗證每一項事實。」本書持續隨 PostgreSQL 版本更新,並在 postgrespro.com 上免費提供完整電子版。

完整摘要#

本書處理的是 PostgreSQL 文獻中一個真實的斷層:官方文件精確但按功能編排,講不出機制之間的因果;而多數實務書籍給的是配方(「把 shared_buffers 設成記憶體的 25%」),讀者照做卻無法判斷這條建議在自己的負載下是否成立。作者的立場是——理解複雜系統的內部機制之後,你才能分析、批判性地評估他人經驗,並得出自己的結論。因此他刻意解釋一些乍看毫無實用價值的細節。

全書七篇由下而上堆疊,前面建立的詞彙是後面的前提。導論建立共用語彙:資料庫叢集、系統目錄、綱要與表空間的層次;一個「關聯」如何在磁碟上被拆成多個分支(主分支、可用空間映射、可見性映射)與 1 GB 一段的檔案,最終落到 8 kB 的頁面,以及長列放不下時的 TOAST 機制;還有多行程架構、共享記憶體,與「每個客戶端一個 backend 行程」帶來的連線池必要性。

隔離與 MVCC 是全書地基。作者先從使用者視角談 SQL 標準的異常現象與三種實際可用的隔離層級,再進入實作:頁面與元組的實體佈局、xminxmax 如何決定可見性、快照的結構與交易水平線(horizon)。這一篇真正的重點在後半——因為 MVCC 讓「更新一列」實際上是寫入一個新版本而非就地修改,膨脹(bloat)就成為必然的副產品,於是頁面修剪、HOT 更新、vacuum 與 autovacuum、凍結(對抗交易 ID 迴繞)、以及表與索引重建,全都是同一個設計決策的下游後果。理解這條因果鏈,是本書給 DBA 最重要的一課。

緩衝快取與 WAL 處理同一個問題的兩面:快取讓資料留在 RAM 換取速度,而 RAM 在當機時全部消失。這一篇拆解緩衝區陣列、pin 與 usage count、時鐘掃描淘汰演算法與大量操作專用的緩衝環,再導出貫穿全篇的單一規則——預寫:任何資料頁面的修改落盤之前,描述它的日誌條目必須先落盤。檢查點、full_page_writes 與同步/非同步提交的所有取捨,都是這條規則的推論。一篇則以「粒度與模式相容性」為判準,涵蓋關聯層級的八種鎖定模式與相容性矩陣、以元組標頭本身實作而不佔共享記憶體的列層級鎖、多重交易、死結偵測,以及作用在記憶體結構上的自旋鎖與輕量鎖。

查詢執行索引種類構成後半的重心。前者從剖析、轉換、規劃、執行四階段講起,核心命題是:規劃器以「成本」為單一比較尺度,而成本建立在基數與選擇性的估算之上——多數糟糕的計畫並非演算法選錯,而是估算失準。因此統計資訊(MCV、直方圖、相關性、多變量統計)被獨立成一節,隨後才是各種掃描方式與三大連接策略(巢狀迴圈含記憶化、雜湊、排序合併)的成本模型。後者把索引討論從 B-tree 延伸到 Hash、GiST、SP-GiST、GIN、BRIN,主線是可擴充性:索引引擎只負責通用部分(取得 TID、檢查可見性、重新檢查條件),而「什麼算相等」「什麼算包含」這類語意全部外包給運算子類別——這條邊界正是 PostgreSQL 能在不改核心的情況下支援新索引與新型別的原因。

結語回到方法論:事實會過時,方法不會;去讀原始碼,開放原始碼是一項極大的優勢。

本書的貢獻與定位#

本書填補的是「PostgreSQL 官方文件」與「PostgreSQL 原始碼」之間長期空著的中間層。與 Bruce Momjian 的簡報式素材相比,它系統得多;與直接讀 src/backend 相比,它不要求讀者懂 C——作者明確表示不預設 C 語言基礎,主要對象是 DBA 與應用程式開發者,但每一節都附上原始碼指引供想挖深的人跟進。

它與同工作區的《The Art of PostgreSQL》正好互補而不重疊:後者站在應用開發者一側,問「怎麼用 SQL 寫更少的程式碼」;本書站在系統一側,問「伺服器收到這段 SQL 之後究竟發生什麼」。與《SQL Performance Explained》相比,後者聚焦 B-tree 索引與跨資料庫的通用調校原則,本書則深入單一產品的實作細節與六種存取方法。

它挑戰的是「照著調校清單設參數就好」的實務習慣:作者刻意不提供食譜,因為配方離開了脈絡就是迷信。主要受眾是需要診斷生產環境異常的 DBA、想理解自己的查詢為何變慢的資深開發者,以及從其他資料庫轉來、想搞清楚差異在哪的工程師。入門使用者會覺得偏難;需要現成解法的人也會失望——本書給的是判斷力,不是答案。