🧭 Giới thiệu
Việc thiết lập sao lưu là điều thiết yếu. Nhưng biết cách khôi phục chúng một cách hiệu quả khi cần thiết còn quan trọng hơn. Đây là lúc PITR (Phục hồi theo thời điểm) phát huy tác dụng, một tính năng mạnh mẽ mà PostgreSQL cung cấp và được quản lý hoàn toàn bởi Barman.
Dù là để sửa lỗi do con người, khôi phục sau một lần triển khai thất bại, hay phân tích trạng thái của cơ sở dữ liệu tại một thời điểm cụ thể, Barman cho phép bạn đưa PostgreSQL trở lại thời gian, phát lại chỉ những thay đổi cho đến một thời điểm xác định.
Trong chương này, chúng ta sẽ khám phá:
- PITR thực sự là gì,
- Các yêu cầu để nó hoạt động,
- Và quan trọng nhất, cách sử dụng nó từng bước với Barman một cách đáng tin cậy.
Sẵn sàng để du hành ngược thời gian với PostgreSQL? Hãy cùng đi nào 👇
🕰️ PITR (Phục hồi theo thời điểm) là gì?
Phục hồi theo thời điểm, hay PITR, là một tính năng mạnh mẽ của PostgreSQL cho phép bạn khôi phục cơ sở dữ liệu về một thời điểm chính xác trong quá khứ.
Nó giống như một chiếc máy thời gian 🕳️🕒.
Hãy tưởng tượng rằng một lỗi hoặc lỗi do con người đã làm hỏng dữ liệu vào sáng nay lúc 10:30. Với PITR, bạn có thể khôi phục cơ sở dữ liệu chính xác như lúc 09:29, ngay trước khi xảy ra sự cố.
Để điều này hoạt động, PostgreSQL ghi lại tất cả các ghi chép cơ sở dữ liệu trong các tệp gọi là WALs (Write Ahead Logs). Các tệp này chứa lịch sử của tất cả các thay đổi đã thực hiện đối với cơ sở dữ liệu.
Barman sử dụng những tệp này để phát lại lịch sử cơ sở dữ liệu cho đến thời điểm đã chọn, bắt đầu từ một bản sao lưu đầy đủ. Nó về cơ bản quay ngược cơ sở dữ liệu về một thời điểm cụ thể được ghi lại bởi các bản sao lưu hiện có.
🎯 RPO và RTO: Hai cột trụ của chiến lược sao lưu/phục hồi vững chắc
Khi nói về tính liên tục của doanh nghiệp và phục hồi sau thảm họa, hai khái niệm là cần thiết để hiểu trước khi xem xét sao lưu hoặc các công cụ như Barman:
📌 Mục tiêu điểm phục hồi (RPO)
RPO, hay Mục tiêu điểm phục hồi, đại diện cho số lượng dữ liệu tối đa mà bạn có thể chấp nhận mất mát trong trường hợp xảy ra sự cố.
👉 Ví dụ:
Nếu bạn có thể chấp nhận mất tối đa 5 phút dữ liệu, RPO của bạn là 5 phút. Điều này có nghĩa là các bản sao lưu (hoặc các bản ghi WAL) của bạn nên diễn ra ít nhất mỗi 5 phút.
⏱ Mục tiêu thời gian phục hồi (RTO)
RTO, hay Mục tiêu thời gian phục hồi, đại diện cho thời gian ngừng hoạt động tối đa có thể chấp nhận sau một sự cố.
👉 Ví dụ:
Nếu bạn coi một gián đoạn dịch vụ 30 phút là chấp nhận được, RTO của bạn là 30 phút. Điều này có nghĩa là các công cụ và cơ chế phục hồi của bạn (như Barman và các quy trình tự động của bạn) phải có khả năng khôi phục và đưa dịch vụ trở lại trực tuyến trong khoảng thời gian này.
⚖️ Tìm kiếm sự cân bằng giữa lý tưởng và thực tế
Chúng ta đều muốn RPO = 0 (không mất dữ liệu) và RTO = 0 (không ngừng hoạt động).
Nhưng trong thực tế, thường có một sự đánh đổi giữa chi phí và tính quan trọng của dịch vụ.
Ví dụ:
- Đối với một trang web giới thiệu, một RPO/RTO vài giờ có thể chấp nhận được.
- Đối với một ứng dụng ngân hàng, từng giây đều quan trọng: RPO/RTO phải gần bằng không.
💡 RPO và RTO với PostgreSQL và Barman
Tin vui: với một cấu hình stack mã nguồn mở tốt, bạn có thể đạt được hiệu suất rất tốt:
-
RPO = 0 🎯
Nhờ vào sao chép đồng bộ của PostgreSQL, dữ liệu của bạn có thể được bảo vệ mà không mất mát. -
RTO tối thiểu ⏱
Bằng cách kết hợp Barman cho việc sao lưu và repmgr cho tính khả dụng cao, phục hồi gần như ngay lập tức có thể xảy ra trong trường hợp có sự cố.
🧰 Các yêu cầu trước khi phục hồi PITR
Trước khi thực hiện phục hồi theo thời điểm, một số yếu tố cần có để quá trình diễn ra suôn sẻ:
-
Sao lưu hợp lệ có sẵn
Bạn phải có ít nhất một bản sao lưu đầy đủ trong Barman. Điều này sẽ phục vụ như là điểm khởi đầu cho việc phục hồi. -
Kích hoạt lưu trữ WAL
PITR phụ thuộc vào việc phát lại các WAL (Ghi nhật ký trước) cho đến một thời điểm chính xác. Đảm bảo rằng việc lưu trữ hoạt động đúng cách và các tệp có mặt trong thư mụcwals
của Barman. -
Không gian đĩa đủ
Việc phục hồi sẽ tạo ra một bản sao mới của cơ sở dữ liệu. Đảm bảo có đủ không gian trống trên máy chủ đích. -
Thời gian hoặc XID cho phục hồi
Để kích hoạt PITR, hãy chỉ định điểm khôi phục, có thể là:
- một ngày/giờ (
'2025-04-11 16:00:00'
), - một ID giao dịch (XID),
- hoặc đơn giản là kết thúc của bản sao lưu (nếu bạn không phát lại các WAL).
- Môi trường thử nghiệm (tùy chọn nhưng được khuyến nghị)
Trước khi phục hồi trong môi trường sản xuất, rất khuyến khích thử nghiệm phục hồi trong một môi trường cô lập.
🔄 Khôi phục dữ liệu với Barman (Ví dụ thực tiễn)
Hãy tạo một bảng trong cơ sở dữ liệu test
của chúng ta và thực hiện một số thao tác để kiểm tra hệ thống sao lưu của chúng ta. Đây là một tập lệnh bạn có thể sử dụng:
--- tạo bảng articles
CREATE TABLE articles (
id SERIAL PRIMARY KEY,
title TEXT,
content TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
--- chèn 20 hàng vào bảng articles
INSERT INTO articles (title, content)
SELECT
'Tiêu đề bài viết ' || i,
'Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.'
FROM generate_series(1, 20) AS s(i);
Tiếp theo, hãy thực hiện một bản sao lưu gia tăng trước khi giả lập việc mất dữ liệu (ví dụ: xóa nhầm) bằng cách sử dụng barman backup pg
(giả sử pg
là máy chủ PostgreSQL của bạn trong cấu hình của Barman):
# trên máy chủ barman
$ barman backup pg
Bắt đầu sao lưu bằng phương pháp rsync-concurrent cho máy chủ pg tại /var/lib/barman/pg/base/20250415T201516
Bắt đầu sao lưu tại LSN: 0/14000028 (000000010000000000000014, 00000028)
Bắt đầu sao chép sao lưu qua rsync/SSH cho 20250415T201516
Sao chép xong (thời gian: 2 giây)
Yêu cầu máy chủ PostgreSQL hoàn tất sao lưu.
Kích thước sao lưu: 38.9 MiB. Kích thước thực tế trên đĩa: 4.8 MiB (-87.55% tỷ lệ khử trùng).
Kết thúc sao lưu tại LSN: 0/14000100 (000000010000000000000014, 00000100)
Sao lưu hoàn tất (thời gian bắt đầu: 2025-04-15 20:15:16.336556, thời gian đã trôi qua: 4 giây)
Xử lý các đoạn xlog từ lưu trữ tệp cho pg
000000010000000000000013
000000010000000000000014
000000010000000000000014.00000028.backup
Lưu ý thời gian kết thúc sao lưu, sẽ được sử dụng để đặt --target-time
trong quá trình phục hồi.
Bây giờ, hãy giả lập mất dữ liệu:
--- xóa bài viết với ID chẵn
DELETE FROM articles WHERE id % 2 = 0;
--- xác minh việc xóa
SELECT COUNT(id) FROM articles;
/*
--------------------------------------------
KẾT QUẢ
--------------------------------------------
*/
count
-------
10
(1 hàng)
💥 Tất cả các bài viết với ID chẵn đã bị xóa. Đây là thời điểm hoàn hảo để sử dụng khôi phục gia tăng và trở về trạng thái ban đầu. Đầu tiên, hãy thực hiện một bản sao lưu mới và dừng máy chủ PostgreSQL:
# trên máy chủ barman
$ barman backup pg
Bắt đầu sao lưu bằng phương pháp rsync-concurrent cho máy chủ pg tại /var/lib/barman/pg/base/20250415T201754
Bắt đầu sao lưu tại LSN: 0/17000028 (000000010000000000000017, 00000028)
Bắt đầu sao chép sao lưu qua rsync/SSH cho 20250415T201754
Sao chép xong (thời gian: 2 giây)
Yêu cầu máy chủ PostgreSQL hoàn tất sao lưu.
Kích thước sao lưu: 38.9 MiB. Kích thước thực tế trên đĩa: 129.7 KiB (-99.67% tỷ lệ khử trùng).
Kết thúc sao lưu tại LSN: 0/17000100 (000000010000000000000017, 00000100)
Sao lưu hoàn tất (thời gian bắt đầu: 2025-04-15 20:17:55.167843, thời gian đã trôi qua: 4 giây)
Xử lý các đoạn xlog từ lưu trữ tệp cho pg
000000010000000000000016
000000010000000000000017
000000010000000000000017.00000028.backup
$ barman list-backup pg
pg 20250415T201754 - Tue Apr 15 20:17:58 2025 - Kích thước: 54.9 MiB - Kích thước WAL: 0 B
pg 20250415T201516 - Tue Apr 15 20:15:19 2025 - Kích thước: 54.9 MiB - Kích thước WAL: 48.0 MiB
pg 20250413T113210 - Sun Apr 13 11:32:14 2025 - Kích thước: 54.8 MiB - Kích thước WAL: 32.0 MiB
# trên máy chủ PostgreSQL
$ sudo service postgresql stop
Hai bản sao lưu bao quanh sự cố: 20250415T201516
và 20250415T201754
. Bản đầu tiên (trước sự cố) sẽ được sử dụng cho PITR.
Để phục hồi, hãy chạy lệnh này trên máy chủ Barman:
$ barman recover --remote-ssh-command "ssh postgres@192.168.58.11" --target-time="2025-04-15 20:17:58.270833+00:00" pg 20250415T201754 /var/lib/postgresql/12/main
Bắt đầu phục hồi từ xa cho máy chủ pg sử dụng bản sao lưu 20250415T201754
Thư mục đích: /var/lib/postgresql/12/main
Lệnh từ xa: ssh postgres@192.168.58.11
Thực hiện PITR. Thời gian phục hồi mục tiêu: '2025-04-15 20:17:58.270833+00:00'
Sử dụng thời gian an toàn cho sao chép rsync thông minh: 2025-04-15 20:17:54.690087+00:00
Sao chép bản sao cơ sở.
Sao chép các đoạn WAL cần thiết.
Tạo cấu hình phục hồi
Xác định các cài đặt nguy hiểm trong thư mục đích.
QUAN TRỌNG
Những cài đặt này đã được thay đổi để ngăn ngừa mất dữ liệu
postgresql.conf dòng 755: archive_command = false
CẢNH BÁO
Bạn cần xem xét các tùy chọn sau như là có thể gây nguy hiểm
postgresql.conf dòng 41: data_directory = '/var/lib/postgresql/12/main' # sử dụng dữ liệu trong thư mục khác
postgresql.conf dòng 43: hba_file = '/etc/postgresql/12/main/pg_hba.conf' # tệp xác thực dựa trên máy chủ
postgresql.conf dòng 45: ident_file = '/etc/postgresql/12/main/pg_ident.conf' # tệp cấu hình xác thực
postgresql.conf dòng 49: external_pid_file = '/var/run/postgresql/12-main.pid' # ghi một tệp PID bổ sung
postgresql.conf dòng 66: unix_socket_directories = '/var/run/postgresql' # danh sách các thư mục phân cách bằng dấu phẩy
postgresql.conf dòng 102: ssl_cert_file = '/etc/ssl/certs/ssl-cert-snakeoil.pem'
postgresql.conf dòng 104: ssl_key_file = '/etc/ssl/private/ssl-cert-snakeoil.key'
postgresql.conf dòng 740: include_dir = 'conf.d' # bao gồm các tệp kết thúc bằng '.conf' từ
Phục hồi hoàn tất (thời gian bắt đầu: 2025-04-16 15:14:41.903013, thời gian đã trôi qua: 8 giây)
Máy chủ PostgreSQL của bạn đã được chuẩn bị thành công cho việc khôi phục!
Tùy chọn lệnh:
--remote-ssh-command
: Lệnh SSH để kết nối với máy chủ PostgreSQL--target-time
: ngày/giờ để khôi phục dữ liệuserver_name
: tên của máy chủbackup_id
: bản sao lưu sẽ sử dụngdestination_directory
: thư mục cho phục hồi
Việc phục hồi có thể được thực hiện trong bất kỳ thư mục nào khác ngoài thư mục chính của PostgreSQL nếu bạn cấu hình lại PostgreSQL để chỉ định thư mục đó. Sau khi phục hồi:
--- xác minh số lượng dữ liệu
SELECT COUNT(id) FROM articles;
/*
--------------------------------------------
KẾT QUẢ
--------------------------------------------
*/
count
-------
20
(1 hàng)
🏁 Kết luận
Những lỗi do con người, sự hỏng hóc phần mềm, hoặc sự cố phần cứng không phải là vấn đề nếu, mà là khi. Trong bối cảnh này, khả năng quay lại PostgreSQL về một trạng thái trước đó chính xác là điều cần thiết.
Với Barman và Phục hồi theo thời điểm (PITR), bạn có một công cụ đáng tin cậy, mạnh mẽ để đảm bảo tính liên tục của doanh nghiệp. Bằng cách kết hợp các bản sao lưu đầy đủ với các tệp WAL đã lưu trữ, bạn có thể khôi phục cơ sở dữ liệu của mình về đúng giây trước khi xảy ra sự cố.
Hơn nữa, như bạn đã thấy, quá trình này có thể được tự động hóa, thử nghiệm và công nghiệp hóa, mang lại rất nhiều lợi ích cho việc nâng cao khả năng phục hồi của kiến trúc PostgreSQL của bạn.