System Design

Write-Ahead Log: database báo ghi xong rồi mất điện, dữ liệu còn không?

Tóm tắt

Với Write-Ahead Log (WAL), mỗi thay đổi được ghi nối tiếp vào log trên đĩa trước rồi mới trả “OK” cho client. Bảng dữ liệu được cập nhật sau. Nếu mất điện, database đọc lại log khi khởi động để khôi phục đủ mọi thay đổi đã xác nhận.

Xem trên Facebook

Database trả về “OK” cho lệnh ghi của bạn, rồi ngay sau đó mất điện. Dữ liệu còn không? Với hầu hết database nghiêm túc, câu trả lời là có — nhờ Write-Ahead Log (WAL). Nguyên tắc: mỗi thay đổi được ghi nối tiếp vào log trên đĩa trước, rồi mới trả “OK” cho client; bảng dữ liệu được cập nhật sau. Khi mất điện, database đọc lại log lúc khởi động để khôi phục đủ mọi thay đổi đã xác nhận.

Diễn biến

  1. Client ghi 6 bản ghi. Mỗi bản được append vào log trên đĩa, xong là trả ack ngay.
  2. Bảng dữ liệu (đang trong RAM) cập nhật chậm hơn: mới có 3 bản.
  3. Mất điện. Phần trong RAM mất sạch; log trên đĩa vẫn đủ 6.
  4. Khởi động lại: database replay log từ bản 1 đến 6 vào bảng. Không mất bản nào.

Vì sao nhanh mà vẫn an toàn?

Ghi vào bảng trực tiếpGhi WAL trước
Ghi ngẫu nhiên vào nhiều trang dữ liệu — chậmGhi nối tiếp (sequential) vào cuối log — nhanh
Mất điện giữa chừng có thể làm trang dữ liệu hỏng dởLog là nguồn sự thật để phục hồi
—Còn được dùng cho replication và point-in-time recovery

Ghi tuần tự lên đĩa nhanh hơn nhiều so với ghi ngẫu nhiên, nên việc thêm bước ghi log không làm lệnh ghi chậm đi nhiều; ngược lại nó cho phép trì hoãn và gom các cập nhật bảng dữ liệu.

Các khái niệm đi kèm

  • Flush/fsync: bắt hệ điều hành ghi thật xuống đĩa; chỉ khi flush xong mới thực sự bền vững.
  • Checkpoint: định kỳ đẩy các thay đổi trong RAM xuống bảng dữ liệu, để log cũ có thể bị bỏ và thời gian khôi phục ngắn lại.
  • Replay/Recovery: khi khởi động, database đọc log từ checkpoint gần nhất để áp lại các thay đổi.
  • Replication: gửi log cho replica để chúng áp lại cùng thay đổi.

Áp dụng thế nào?

  • Hiểu “ack” nghĩa là gì: trong PostgreSQL, ack đến từ WAL đã flush xuống đĩa (khi synchronous_commit bật), không phải từ bảng.
  • Cân nhắc đánh đổi: tắt flush đồng bộ để nhanh hơn đồng nghĩa có thể mất vài giao dịch cuối khi sự cố.
  • Vận hành: theo dõi dung lượng WAL và archive WAL để phục vụ backup và khôi phục theo thời điểm.
  • Hạ tầng: đĩa có cache ghi không an toàn có thể phá vỡ đảm bảo; kiểm tra cấu hình lưu trữ.

Nguồn & tham khảo

  1. Write-Ahead Logging (WAL) — PostgreSQL Docs