
MVCC trong PostgreSQL thực sự tệ hại? Sự thật đằng sau thiết kế 40 năm tuổi
Phân tích chuyên sâu về cơ chế MVCC của PostgreSQL, lý do tại sao nó bị chỉ trích về hiệu năng và sự so sánh công bằng với các hệ quản trị cơ sở dữ liệu khác trên thị trường.
Bài viết được dịch và tổng hợp từ tin tức gốc. Bạn có thể đọc bài viết gốc bằng tiếng Anh tại đây.
Điểm tin nhanh:
- MVCC của PostgreSQL bị chỉ trích vì gây ra tình trạng phình to dữ liệu (bloat) và khuếch đại ghi (write amplification).
- Mọi cơ chế MVCC đều phải đánh đổi: hoặc là gánh nặng cho writer, hoặc cho reader, hoặc cho hệ thống thu gom rác (garbage collection).
- Vấn đề không nằm ở lỗi thiết kế, mà là sự lựa chọn kiến trúc: PostgreSQL ưu tiên sự đơn giản và tính nhất quán ở mức độ thực thi.
Nếu bạn đã từng nghe những lời phàn nàn rằng PostgreSQL là một thảm họa về hiệu năng do cơ chế MVCC (Multi-Version Concurrency Control) lỗi thời, thì bạn không hề đơn độc. Từ những tranh cãi về việc Uber từ bỏ Postgres cho đến những chỉ trích gay gắt từ các chuyên gia cơ sở dữ liệu hàng đầu, MVCC thường bị coi là "tội đồ" gây ra tình trạng phình to bảng, lãng phí tài nguyên và những cơn ác mộng mang tên VACUUM. Nhưng liệu chúng ta có đang nhìn nhận vấn đề một cách phiến diện khi quên đặt câu hỏi: So với cái gì?

Bốn cáo buộc chống lại PostgreSQL
Cơ chế MVCC của PostgreSQL hoạt động dựa trên nguyên tắc: một lệnh UPDATE không bao giờ thực sự sửa đổi dữ liệu cũ. Thay vào đó, nó ghi một bản sao mới vào heap, đánh dấu bản cũ bằng t_xmax và để cả hai cùng tồn tại trên đĩa. Việc dọn dẹp (cleanup) hoàn toàn phụ thuộc vào tiến trình VACUUM.
1. Khuếch đại ghi (Write Amplification)
Đây là tâm điểm của những lời phàn nàn. Vì mọi chỉ mục (index) trong Postgres đều trỏ đến vị trí vật lý (ctid) của hàng dữ liệu, nên khi một hàng được cập nhật và di chuyển sang trang mới, mọi chỉ mục liên quan đều phải được cập nhật theo. Điều này làm tăng lượng WAL (Write Ahead Log) đáng kể.
| Loại bảng | WAL Records | WAL Bytes | WAL Pretty |
|---|---|---|---|
| Bảng tinh gọn (Lean) | 302,510 | 38,218,531 | 36 MB |
| Bảng có chỉ mục | 709,440 | 72,394,573 | 69 MB |
Lưu ý: Sự khác biệt về WAL giữa bảng có chỉ mục và bảng không có chỉ mục cho thấy chi phí đắt đỏ của việc duy trì tính nhất quán vật lý trong Postgres.
2. Bảng dữ liệu trở thành hiện trường vụ án
Việc lưu trữ các bản ghi cũ ngay trong bảng chính khiến dữ liệu bị phân mảnh nghiêm trọng. Nếu không được VACUUM kịp thời, bảng của bạn sẽ phình to gấp đôi, gấp ba kích thước thực tế, làm giảm hiệu suất truy vấn đáng kể. Điều này tương tự như cách chúng ta phải hiện đại hóa hệ thống Legacy với AI để tránh những rào cản kỹ thuật tích tụ theo thời gian.
3. Giao dịch nhàn rỗi (Idle Transaction) làm tê liệt hệ thống
Một giao dịch mở quá lâu mà không kết thúc sẽ ngăn cản VACUUM dọn dẹp các tuple chết, dẫn đến tình trạng bloat không kiểm soát. Đây là điểm yếu chí tử mà các hệ thống như Bitweave thường tìm cách tối ưu hóa bằng các kiến trúc lưu trữ khác biệt.
So sánh với các hệ thống khác
Mọi cơ sở dữ liệu đều phải trả lời 4 câu hỏi thiết kế MVCC:
- Dữ liệu cũ nằm ở đâu?
- Hướng của chuỗi phiên bản (version chain) là gì?
- Chỉ mục trỏ vào đâu?
- Ai chịu trách nhiệm dọn dẹp?
PostgreSQL chọn cách lưu dữ liệu cũ tại chỗ, chuỗi phiên bản từ cũ đến mới, chỉ mục trỏ vào vị trí vật lý và dọn dẹp bằng tiến trình nền. Các hệ thống khác như Oracle hay InnoDB chọn cách sử dụng Undo log, trong khi các hệ thống LSM (Log-Structured Merge-tree) lại đẩy gánh nặng sang quá trình nén (compaction). Không có giải pháp nào là hoàn hảo, tất cả chỉ là sự đánh đổi về chi phí vận hành.
Đánh giá & Lời khuyên Thực tiễn
Từ góc độ của một kỹ sư hệ thống, MVCC của PostgreSQL không phải là lỗi thiết kế mà là một sự đánh đổi có chủ đích.
- Ưu điểm: Đảm bảo tính nhất quán cao, khả năng đọc không chặn ghi cực tốt, và kiến trúc dễ dự đoán.
- Nhược điểm: Đòi hỏi sự hiểu biết sâu sắc về VACUUM và quản lý chỉ mục. Nếu không cấu hình đúng, hệ thống sẽ nhanh chóng bị bloat.
- Lời khuyên:
- Luôn theo dõi các chỉ số bloat của bảng và chỉ mục.
- Sử dụng HOT (Heap-Only Tuples) update bằng cách giữ fillfactor phù hợp.
- Tránh các giao dịch kéo dài trên môi trường Production.
- Nếu bạn đang xây dựng hệ thống dữ liệu phức tạp, hãy cân nhắc việc xây dựng quy trình Porting phần mềm dựa trên kiểm thử tự động để đảm bảo các thay đổi về cấu trúc bảng không gây ra tác động tiêu cực.
Câu hỏi thường gặp (FAQ)
Tại sao PostgreSQL không thay đổi cơ chế MVCC của mình?
Thay đổi hoàn toàn MVCC đồng nghĩa với việc viết lại toàn bộ nhân của PostgreSQL, điều này sẽ phá vỡ tính ổn định và độ tin cậy mà hàng triệu người dùng đang dựa vào.
Làm thế nào để giảm thiểu tác động của MVCC?
Việc cấu hình VACUUM tự động (autovacuum) hợp lý, sử dụng fillfactor và tránh cập nhật các cột được đánh chỉ mục là những cách hiệu quả nhất.
Có hệ thống nào tốt hơn PostgreSQL về MVCC không?
Không có hệ thống nào "tốt hơn" tuyệt đối, chỉ có hệ thống "phù hợp hơn" với workload của bạn. Các hệ thống như InnoDB hay SQL Server có những ưu điểm riêng nhưng cũng đi kèm với những hạn chế khác về mặt kiến trúc.
Kết luận
MVCC của PostgreSQL có thể không hoàn hảo, nhưng nó là một minh chứng cho sự đánh đổi kỹ thuật bền vững suốt 40 năm qua. Thay vì tìm kiếm một giải pháp hoàn hảo không tồn tại, hãy học cách làm chủ cơ chế hiện có của nó. Nếu bạn quan tâm đến việc tối ưu hóa hạ tầng dữ liệu, hãy theo dõi các bài viết chuyên sâu tiếp theo trên hi_dev để cập nhật những kiến thức mới nhất về công nghệ backend và database.
Do you like this post?
Upvote to push this post higher on the community feed




