Khi bạn làm việc với database, mọi thứ nhìn có vẻ đơn giản lắm: thêm dòng, update record, xoá khách hàng. Nhưng đằng sau sự đơn giản đó là một cơ chế cực kỳ phức tạp và thông minh. Thực ra thì dữ liệu này nằm ở đâu? Làm sao PostgreSQL không bị mất gì, kể cả khi server bị tắt đột ngột?
Để hiểu rõ, cần nắm hai thứ chính: dữ liệu (bảng, index, info hệ thống) thực sự nằm ở đâu trên ổ cứng, và cơ chế bảo vệ dữ liệu hoạt động thế nào — transaction log, hay còn gọi là WAL (Write-Ahead Logging).
Toàn bộ database PostgreSQL được lưu thành một loạt file trong một thư mục đặc biệt — data_directory. Thường nó nằm ở đây:
/var/lib/postgresql/17/main
Trong folder này là trái tim của database: bảng, index, meta info, config. WAL log cũng nằm ở đây — cơ chế đầu tiên nhận mọi thay đổi. Trước khi dữ liệu được ghi vào bảng trên ổ cứng, nó sẽ được ghi vào WAL trước. Kiểu như bản nháp, database ghi lại từng bước, để nếu có sự cố thì vẫn khôi phục được mọi thứ đến tận thao tác cuối cùng.
Nhờ cách này, PostgreSQL đảm bảo độ tin cậy và ổn định, kể cả trong điều kiện "lởm" nhất.
Bảng (Table)
Mỗi bảng thực chất là một file riêng biệt hoặc một nhóm file. Các file này nằm trong subfolder base/. Cấu trúc kiểu như này:
$PGDATA/base/
├── 16384/
│ ├── 12345 ← bảng
│ ├── 12346 ← index
│ └── ...
16384— là ID nội bộ của database (OID).12345— là ID của bảng cụ thể.
Nếu bảng to, PostgreSQL sẽ chia nó thành các segment mỗi cái 1GB:
12345
12345.1
12345.2
...
Các file này không chứa "dòng" như CSV text đâu — nó là dạng "trang nhị phân" 8KB một trang.
WAL: Write-Ahead Logging — không chỉ là "log" bình thường
Giờ đến một phần cực kỳ quan trọng và hay bị hiểu nhầm trong PostgreSQL — WAL, hay Write-Ahead Logging. Dù tên có chữ log, WAL không phải là file log text bình thường như error log hay query log đâu. Đây là cơ chế sống còn để đảm bảo đồng nhất và phục hồi dữ liệu, hoạt động ở tầng thấp nhất của file system.
WAL không phải là báo cáo sự kiện, mà là ghi trước mọi thay đổi mà PostgreSQL sẽ thực hiện với dữ liệu. Việc ghi này diễn ra trước khi bảng thực sự bị sửa trên ổ cứng. Đó là lý do gọi là write-ahead — "ghi trước".
Khi bạn, ví dụ, insert một dòng mới vào bảng, PostgreSQL sẽ:
- KHÔNG update bảng trên ổ cứng ngay — làm vậy vừa chậm vừa nguy hiểm.
- Ghi vào WAL trước, rằng dòng này sẽ được thêm vào.
- Sau đó, khi tiện (ví dụ background process), dữ liệu mới thực sự được ghi vào bảng.
Nó giống như ký séc ở ngân hàng: bạn ký séc (WAL), rồi ngân hàng mới update tài khoản (bảng). Nếu có gì trục trặc — séc vẫn còn, làm lại thao tác được.
Định dạng và cấu trúc WAL
- WAL file lưu ở dạng nhị phân.
- Mỗi file là dòng các thao tác được sắp xếp chặt chẽ, mô tả thay đổi bên trong của các trang dữ liệu, cấu trúc index, commit, v.v.
- Một WAL file có size cố định — mặc định là 16MB.
Lưu ý: WAL không chứa "SQL command" hay "dòng bảng" như bạn quen. Nó chứa instruction cho engine PostgreSQL để tái hiện lại thay đổi, từng trang một.
Nếu bị crash thì sao?
Nếu server PostgreSQL bị tắt đột ngột — ví dụ mất điện — thì cũng không mất hết đâu. Khi khởi động lại, database không hoảng loạn, mà sẽ load từ ổ cứng phiên bản dữ liệu "ổn định" cuối cùng. Sau đó nó lấy transaction log (WAL), trong đó còn lưu mọi thay đổi mới nhất, và từ từ "apply" chúng — thực hiện nốt những gì chưa kịp ghi vào file chính. Kết quả là database phục hồi về trạng thái đồng nhất hoàn toàn, như chưa có gì xảy ra.
WAL còn làm được gì nữa?
Point-In-Time Recovery (PITR). Lưu WAL file cho phép phục hồi database đến bất kỳ thời điểm nào giữa hai lần backup đầy đủ.
Streaming replication. PostgreSQL có thể gửi WAL record sang server khác real-time. Nhờ đó có thể duy trì hot replica — bản sao database luôn đồng bộ với bản chính.
Incremental recovery. Kết hợp với backup đầy đủ, WAL cho phép phục hồi chỉ những thay đổi, không cần copy lại toàn bộ database.
Tạo backup nhị phân: pg_basebackup
Nếu bạn đã quen với pg_dump rồi thì biết nó rất hợp để tạo backup logic (tức là copy cấu trúc và dữ liệu database thành SQL query). Nhưng nếu bạn cần backup vật lý thì sao? Ví dụ, copy nguyên xi toàn bộ file database? Lúc này dùng tool pg_basebackup nhé.
pg_basebackup là utility giúp tạo bản sao vật lý của dữ liệu PostgreSQL. Nó cực kỳ hữu ích cho database lớn, khi cần quản lý quá trình phục hồi hiệu quả. Ưu điểm lớn nhất của pg_basebackup là nó làm việc này rất nhanh.
Cú pháp cơ bản của lệnh pg_basebackup
Làm việc với pg_basebackup bắt đầu từ việc hiểu lệnh của nó. Bạn chạy trên terminal, cú pháp cơ bản như sau:
pg_basebackup -D /backup_directory -F tar -z -P
Giải thích từng phần nhé:
-D /backup_directory— chỉ định folder sẽ lưu file backup của bạn.-F tar— định dạng dữ liệu. Optiontartạo file archive dạng.tar. Bạn cũng có thể dùngplainđể tạo cấu trúc file database.-z— nén backup lại, giúp tiết kiệm dung lượng ổ cứng. Backup nhẹ nhàng ai mà chả thích!-P— hiện tiến trình real-time. Nhìn thấy process chạy, yên tâm là server không "đơ".
Ví dụ sử dụng:
pg_basebackup -D /backups/university_backup -F tar -z -P
Sau khi chạy lệnh, trong folder /backups/university_backup sẽ có bản backup dạng .tar.
Ưu điểm khi dùng pg_basebackup
Hiệu quả: backup incremental giúp không lặp lại dữ liệu không đổi, tiết kiệm cả thời gian lẫn dung lượng.
Dễ dùng: tool pg_basebackup tự động xử lý mọi chi tiết, kể cả WAL file.
Đáng tin cậy: nhờ tích hợp với cơ chế PostgreSQL, pg_basebackup tạo bản sao chính xác toàn bộ database, phục hồi cực dễ.
Ví dụ sử dụng
Giờ đến phần thực hành. Dưới đây là ví dụ thực tế về cách dùng pg_basebackup để backup database PostgreSQL. Sẽ chỉ cách backup cơ bản, cách thêm nén, và cách bật archive WAL để phục hồi "đến từng thời điểm". Các lệnh này hợp cho cả newbie lẫn ai muốn nâng cao.
Tạo backup cơ bản
pg_basebackup -D /backups/full_backup -F tar -z -P
Kết quả: backup đầy đủ database trong file .tar.
Cấu hình nén và định dạng
Tạo backup dữ liệu với mức nén cao nhất:
pg_basebackup -D /backups/full_backup -F tar -z -Z 9 -P
Ở đây -Z 9 là mức nén (max là 9).
Archive WAL
Nếu bật archive WAL, database có thể phục hồi đến bất kỳ thời điểm nào. Lệnh để backup WAL:
pg_basebackup -D /backups/incremental_backup -F tar -z -P --wal-method=archive
GO TO FULL VERSION