CodeGym /課程 /SQL SELF /PostgreSQL 怎麼存資料:資料庫結構與交易日誌(WAL)

PostgreSQL 怎麼存資料:資料庫結構與交易日誌(WAL)

SQL SELF
等級 43 , 課堂 4
開放

你在用資料庫的時候,感覺一切都很簡單:加一行、更新一筆、刪掉一個客戶。但這背後其實藏著一套很複雜又設計精良的機制。那些資料到底存在哪?PostgreSQL 怎麼做到就算伺服器突然斷電也不會掉資料?

要搞懂這些,你得先知道兩個重點:資料(table、index、系統資訊)實際上放在哪裡,還有資料保護機制怎麼運作——也就是交易日誌,WAL(Write-Ahead Logging)。

整個 PostgreSQL 資料庫其實就是一堆檔案,放在一個特定的資料夾裡——data_directory。通常會在這裡:

/var/lib/postgresql/17/main

這個資料夾就是資料庫的心臟:table、index、meta 資訊、設定檔全都在這。WAL 日誌也在這裡——這個機制會最先收到所有變更。資料還沒寫進 table 檔案前,會先寫進 WAL。這就像草稿本,資料庫會把每一步都記下來,萬一出事就能還原到最後一個操作。

靠這種設計,PostgreSQL 就算遇到很不穩的狀況也能保證資料安全跟穩定。

Table

每個 table 實際上就是一個獨立檔案或一組檔案。這些檔案會放在 base/ 子目錄。結構大概長這樣:

$PGDATA/base/
├── 16384/
│   ├── 12345   ← 資料表
│   ├── 12346   ← 索引
│   └── ...
  • 16384 — 這是資料庫的內部 ID(OID)。
  • 12345 — 這是某個 table 的 ID。

如果 table 很大,PostgreSQL 會把它切成 1GB 的 segment

12345
12345.1
12345.2
...

這些檔案不是像 CSV 那樣存「一行一行」的文字——而是 8KB 的「二進位 page」格式。

WAL: Write-Ahead Logging 不是普通的「log」

現在來講 PostgreSQL 裡最重要、但常常被誤解的東西——WAL,也就是Write-Ahead Logging。雖然名字裡有 log,但 WAL 不是一般的文字 log 檔,不像 error log 或 query log。它是資料一致性跟還原的關鍵機制,直接在檔案系統的低階層級運作。

WAL 不是事件報告,而是所有變更的預先記錄,PostgreSQL 打算對資料做什麼都會先寫進這裡。這個記錄會在實際改 table 檔案之前就寫好。所以才叫 write-ahead——「先寫再說」。

比如你插入一行新資料,PostgreSQL 會:

  1. 不會馬上改 table 檔案——這樣太慢也不安全。
  2. 先寫進 WAL,記下這行要加進去。
  3. 等到適合的時候(像是 background process),才真的把資料寫進 table。

這就像銀行支票:你先簽名(WAL),銀行之後才會更新帳戶(table)。如果出問題——支票還在,可以重來一次。

WAL 的格式與結構

  • WAL 檔案是二進位格式。
  • 每個檔案都是嚴格排序的操作流程,描述資料 page、index 結構、commit 等等的內部變更。
  • 一個 WAL 檔案大小固定——預設是 16MB。

重點:WAL 裡沒有「SQL 指令」或「table row」這種東西。它存的是PostgreSQL 引擎的指令,教它怎麼一頁一頁還原變更。

如果發生故障會怎樣?

如果 PostgreSQL 伺服器突然掛掉——比如突然斷電——也不用怕。下次啟動時,資料庫不會慌張,而是會從硬碟載入最後一個「穩定」的資料版本。然後它會拿出 WAL 日誌,裡面有所有最近的變更,慢慢「補上」那些還沒寫進主要檔案的東西。最後資料庫就會回到完全一致的狀態,好像什麼事都沒發生過一樣。

WAL 的進階功能

Point-In-Time Recovery (PITR)。 只要有 WAL 檔案,就能把資料庫還原到任意時間點,只要在兩個完整備份之間。

串流複製(Streaming Replication)。 PostgreSQL 可以即時把 WAL 記錄傳到另一台伺服器。這樣就能維護熱備份——跟主資料庫同步的複本。

增量還原(Incremental Recovery)。 配合完整備份,WAL 可以只還原變更的部分,不用整個資料庫重來。

建立二進位備份:pg_basebackup

如果你用過 pg_dump,就知道它很適合做邏輯備份(把資料庫結構跟資料存成 SQL 指令)。但如果你要做物理備份呢?比如要完整鏡像所有資料庫檔案?這時候就要用 pg_basebackup 這個工具了。

pg_basebackup 是個可以建立 PostgreSQL 實體資料複本的工具。對大型資料庫來說,這很方便,還原起來也有效率。pg_basebackup 最大的優點就是超快。

pg_basebackup 的基本指令語法

pg_basebackup 前要先搞懂它的指令。你在終端機下這樣打:

pg_basebackup -D /backup_directory -F tar -z -P

來拆解一下:

  • -D /backup_directory — 指定備份檔要存到哪個資料夾。
  • -F tar — 資料格式。tar 會做成 .tar 壓縮檔。你也可以用 plain,這樣會直接複製資料夾結構。
  • -z — 壓縮備份,省空間。誰不想備份小一點?
  • -P — 顯示即時進度。這樣你就知道有在跑,不會以為卡住了。

範例:

pg_basebackup -D /backups/university_backup -F tar -z -P

執行完後,/backups/university_backup 這個資料夾裡就會有一個 .tar 格式的備份檔。

pg_basebackup 的好處

效率:增量備份不用重複存沒變的資料,省時間又省空間。

簡單:pg_basebackup 會自動處理所有細節,連 WAL 檔都幫你搞定。

可靠:因為跟 PostgreSQL 機制整合,pg_basebackup 做出來的備份很精準,還原也很簡單。

實戰範例

來點實作吧。下面是一些用 pg_basebackup 做 PostgreSQL 備份的真實例子。會教你怎麼做基本備份、怎麼加壓縮、還有怎麼開啟 WAL 日誌歸檔,這樣就能做「時間點還原」。這些指令新手老手都用得到。

建立基本備份

pg_basebackup -D /backups/full_backup -F tar -z -P

結果:你會拿到一個 .tar 格式的完整資料庫備份。

設定壓縮跟格式

來做一個高壓縮的備份:

pg_basebackup -D /backups/full_backup -F tar -z -Z 9 -P

這裡 -Z 9 是壓縮等級(最高 9)。

WAL 歸檔

如果你有設定 WAL 歸檔,資料庫就能還原到任何時間點。這是設定 WAL 備份的指令:

pg_basebackup -D /backups/incremental_backup -F tar -z -P --wal-method=archive
1
問卷/小測驗
備份入門,等級 43,課堂 4
未開放
備份入門
備份入門
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION