Lập trình 22/09/2026 6 phút

HOT update và index-only scan: hai tối ưu MVCC mà fillfactor và index che phủ mở khóa

UPDATE trong PostgreSQL thường phải ghi lại mọi index — trừ khi là HOT update. Bài này đo thật trên pg-lab: với fillfactor mặc định 100, cập nhật cột không-index vẫn cho 0 HOT (trang đầy); hạ xuống 70 thì 4.368/10.000 là HOT (không ghi index). Và index-only scan cho Heap Fetches=0 khi query chỉ cần cột trong index, giảm I/O rõ rệt.

Lập trình 22/09/2026 6 phút

WAL trong PostgreSQL: vì sao ghi log trước khi ghi dữ liệu, và đo lượng WAL mỗi thao tác sinh ra

Độ bền của PostgreSQL đến từ WAL (write-ahead log): mọi thay đổi ghi vào log tuần tự và fsync xuống đĩa trước, trang dữ liệu ghi sau. Bài này đo thật trên pg-lab lượng WAL sinh ra: INSERT 10.000 hàng tạo 861 kB, COPY cùng dữ liệu chỉ 357 kB, UPDATE nặng nhất 1.645 kB, còn SELECT không sinh WAL. Kèm đánh đổi fsync và synchronous_commit.

Lập trình 22/09/2026 6 phút

SKIP LOCKED: xây hàng đợi công việc ngay trong PostgreSQL, 4 worker không đụng nhau

Bạn không phải lúc nào cũng cần RabbitMQ hay SQS cho hàng đợi công việc — PostgreSQL làm được bằng SELECT FOR UPDATE SKIP LOCKED. Bài này đo thật trên pg-lab: 4 worker chạy song song vét sạch 300 job, chia đều 76/75/75/74, mỗi job xử lý đúng một lần, không trùng, không chờ khóa. Kèm advisory lock cho khóa mức ứng dụng.

Lập trình 22/09/2026 6 phút

Tổng kết đồng thời PostgreSQL: khung tư duy và checklist tránh bug concurrency

Mười một bài, mười một phép đo thật bằng nhiều phiên psql đồng thời. Bài tổng kết này nối tất cả — MVCC, bốn mức cô lập, lost update, write skew, khóa hàng, deadlock, bloat, vacuum, HOT, WAL, SKIP LOCKED — thành một bảng số liệu và một checklist thực chiến: cần đảm bảo gì thì dùng gì, cạm bẫy đồng thời nào cần tránh, và vì sao mọi thứ bắt nguồn từ MVCC.

Lập trình 22/09/2026 7 phút

Outbox pattern: vì sao ghi database rồi publish message là cái bẫy mất dữ liệu

Service ghi đơn hàng vào database rồi publish message sang Kafka — hai bước riêng. Nếu crash giữa hai bước, database có đơn mà message biến mất. Bài này chạy thật: dual-write để lệch 40/100 đơn; outbox pattern ghi business row và outbox row trong cùng một transaction PostgreSQL, relay đọc và publish — khớp 100%, và relay chạy lại vẫn an toàn. Chìa khoá là tính nguyên tử của database.

Lập trình 22/09/2026 7 phút

Vì sao cache: đo thật Redis nhanh hơn query database 30 đến 300 lần

Cache nghe như giải pháp vạn năng cho hiệu năng, nhưng nhanh hơn bao nhiêu và khi nào mới đáng? Bài này đo thật: một query gộp 100.000 dòng trên PostgreSQL tốn 8.2ms mỗi lần tính; cache kết quả vào Redis thì GET chỉ 0.028ms (pipelined) hoặc 0.26ms (round-trip đơn) — nhanh hơn 30 đến 300 lần. Nhưng nói thẳng: với query đơn giản lấy một dòng theo khoá chính, chênh lệch nhỏ hơn nhiều. Cache thắng rõ khi tính toán gốc đắt.