Bật/tắt chế độ Wal2
- Chế độ "Wal2" của SQLite rất giống với chế độ "wal (Write-Ahead Logging)".
- Để chuyển cơ sở dữ liệu sang chế độ wal2, dùng lệnh
PRAGMA journal_mode = wal2;.
- Không thể chuyển trực tiếp từ chế độ "wal" sang "wal2"; trước tiên phải chuyển sang chế độ rollback.
- Để chuyển cơ sở dữ liệu từ chế độ wal sang wal2, dùng
PRAGMA journal_mode = delete; rồi sau đó PRAGMA journal_mode = wal2;.
- Cơ sở dữ liệu ở chế độ wal2 chỉ có thể được truy cập bằng các phiên bản SQLite được biên dịch từ nhánh đó.
- Nếu cố dùng phiên bản SQLite khác, sẽ phát sinh lỗi SQLITE_NOTADB.
- Để chuyển cơ sở dữ liệu wal2 sang chế độ rollback để mọi phiên bản SQLite đều có thể truy cập, dùng lệnh
PRAGMA journal_mode = delete;.
Ưu điểm của chế độ Wal2
- Trong chế độ wal hiện có, khi writer ghi dữ liệu vào cơ sở dữ liệu, tệp cơ sở dữ liệu không bị sửa trực tiếp mà dữ liệu mới được nối thêm vào tệp "-wal".
- Các thao tác đọc sẽ đọc dữ liệu từ cả tệp cơ sở dữ liệu gốc và tệp "-wal".
- Tại một thời điểm nào đó, dữ liệu sẽ được sao chép từ tệp "-wal" sang tệp cơ sở dữ liệu; việc này được gọi là "checkpoint".
- Checkpoint có thể được thực hiện tường minh qua
PRAGMA wal_checkpoint hoặc sqlite3_wal_checkpoint_v2(), hoặc tự động bằng cách cấu hình PRAGMA wal_autocheckpoint (thiết lập mặc định).
- Checkpointer không chặn writer, và writer cũng không chặn checkpointer.
- Tuy nhiên, nếu writer ghi vào cơ sở dữ liệu trong lúc checkpoint đang diễn ra, dữ liệu mới sẽ tiếp tục được nối vào cuối tệp wal, khiến tệp wal có thể tiếp tục phình to.
- Ở chế độ wal2, không còn vấn đề tệp wal tăng kích thước vô hạn ngay cả khi checkpointer không có cơ hội hoàn tất mà không bị gián đoạn.
- Chế độ wal2 dùng hai tệp wal thay vì một ("-wal" và "-wal2").
- Khi dữ liệu được ghi, writer bắt đầu nối dữ liệu mới vào tệp wal thứ nhất.
- Khi tệp wal thứ nhất đủ lớn, writer sẽ bắt đầu nối dữ liệu vào tệp wal thứ hai.
- Sau đó, tệp wal thứ nhất có thể được checkpoint; khi tệp wal thứ hai đủ lớn và tệp thứ nhất đã được checkpoint, hệ thống sẽ chuyển lại sang tệp thứ nhất.
Lập trình ứng dụng
- Từ góc nhìn người dùng, khác biệt chính giữa chế độ wal và wal2 liên quan đến checkpoint.
- Ở chế độ wal, có thể thử checkpoint bất cứ lúc nào; nhưng ở chế độ wal2, chỉ có thể checkpoint sau khi writer đã chuyển sang tệp wal "còn lại".
- Ở chế độ wal, sau khi transaction được commit, wal-hook (callback) được gọi với đối số là tổng số trang của tệp wal.
- Ở chế độ wal2, wal-hook được gọi với đối số là tổng số trang chưa được checkpoint trong cả hai tệp wal, hoặc với đối số 0 nếu tệp wal "còn lại" đang trống hoặc đã được checkpoint.
- Khuyến nghị client sử dụng cùng chiến lược checkpoint cho cơ sở dữ liệu wal2 như với chế độ wal.
- Wal-hook được gọi sau khi transaction được commit xuống đĩa và khóa cơ sở dữ liệu được giải phóng, nhưng vẫn xảy ra bên trong lời gọi
sqlite3_step().
- Trong hệ thống BEGIN CONCURRENT, thay vì chạy checkpoint bên trong wal-hook, có thể dùng một luồng trì hoãn công việc này cho đến sau khi application mutex được giải phóng.
Ý kiến của GN⁺
- Chế độ wal2 của SQLite cung cấp một phương thức journaling mới giúp cải thiện tính đồng thời và hiệu quả của cơ sở dữ liệu.
- Việc giải quyết vấn đề tệp wal tăng không giới hạn là điều quan trọng để cải thiện độ ổn định và hiệu năng của hệ thống.
- Với việc đưa vào wal2, các nhà phát triển cần xem xét lại chiến lược checkpoint của cơ sở dữ liệu và triển khai logic checkpoint phù hợp để đạt được khả năng đồng thời tốt hơn.
1 bình luận
Ý kiến trên Hacker News
Bedrock
Có cung cấp liên kết tới left-right primitive, một kỹ thuật tương tự chế độ WAL2.
Microsoft SQL Server dùng một kiến trúc tương tự, nhưng thay vì các tệp log riêng biệt, nó cấp phát các Virtual Log Files (VLF) bên trong tệp log vật lý (trên đĩa). Các VLF được cấp phát trong một ring buffer và có thể lên tới hàng nghìn.
Có thể thấy tính năng này vẫn chưa được phát hành.
Tôi luôn băn khoăn rằng WAL tồn tại để giúp duy trì tính toàn vẹn dữ liệu và phục hồi sau sự cố. Tuy nhiên, bản thân tệp này được ghi theo lô (được commit xuống đĩa một cách đáng tin cậy) chứ không phải sau mọi thay đổi của cơ sở dữ liệu, nhằm đạt hiệu năng. Điều này chẳng phải làm suy yếu mục đích đó sao? Nói chung, không chỉ riêng cơ sở dữ liệu này, tôi vẫn chưa tìm được câu trả lời cho vấn đề đó.
Tò mò không biết điều này sẽ ảnh hưởng thế nào tới các hệ thống SQLite phân tán mới như Litestream.
Vậy về cơ bản đây là double buffering cho cơ sở dữ liệu? Nghe hợp lý đấy.
Chế độ WAL2 đã được đưa vào benchmark của nghiên cứu backend HC-tree.