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

Read Committed vs Repeatable Read: cùng code, kết quả khác — và lost update âm thầm

Hai mức cô lập trông giống nhau cho đến khi có ghi đồng thời. Bài này đo thật trên pg-lab mẫu đọc-tính-ghi kinh điển: ở Read Committed, hai giao dịch cùng +10 cho kết quả 110 thay vì 120 — lost update âm thầm, không báo lỗi. Ở Repeatable Read, PostgreSQL phát hiện và báo could not serialize access, buộc thử lại — và lần thử lại cho đúng 120.

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

Serializable và write skew: lỗi đồng thời mà Repeatable Read không bắt được

Có một loại bug đồng thời tinh vi hơn lost update: hai giao dịch đọc chung một điều kiện rồi ghi hai hàng khác nhau, phá vỡ một ràng buộc mà không cái nào tự biết. Bài này đo thật trên pg-lab ví dụ hai bác sĩ cùng xin nghỉ: ở Repeatable Read cả hai thành công và còn 0 người trực (sai), ở Serializable một giao dịch bị hủy với lỗi read/write dependencies và ràng buộc được giữ.

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

Khóa hàng trong PostgreSQL: FOR UPDATE, lock wait, và cách chẩn đoán query bị treo

MVCC giúp đọc không chặn ghi, nhưng khi cần 'đọc rồi chắc chắn ghi' bạn phải khóa hàng tường minh bằng FOR UPDATE. Bài này đo thật trên pg-lab: phiên thứ hai chờ 2.535 ms cho phiên thứ nhất nhả khóa cùng hàng, quan sát pg_locks và wait_event=Lock/transactionid, và NOWAIT báo lỗi ngay thay vì chờ. Hai view vàng để chẩn đoán treo vì khóa.

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

Deadlock trong PostgreSQL: khóa chéo, 'deadlock detected', và cách tránh bằng thứ tự khóa

Hai giao dịch khóa chéo nhau — A giữ hàng 1 xin hàng 2, B giữ hàng 2 xin hàng 1 — là công thức của deadlock. Bài này tạo deadlock thật trên pg-lab: PostgreSQL tự phát hiện vòng chờ và hủy một nạn nhân với ERROR deadlock detected, giao dịch kia đi tiếp. Và cách tránh triệt để: luôn khóa các hàng theo cùng một thứ tự.

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

Bloat trong PostgreSQL: vì sao cập nhật một hàng 100.000 lần làm bảng phình lên 3,5 MB

MVCC khiến mỗi UPDATE để lại một bản chết thay vì sửa tại chỗ — và chúng tích tụ thành bloat. Bài này đo thật trên pg-lab: một bảng chỉ có 1 hàng sống, sau 100.000 lần UPDATE phình từ 8 KB lên 3,5 MB. VACUUM dọn bản chết nhưng không trả đĩa; chỉ VACUUM FULL mới thu nhỏ file về 8 KB — nhưng khóa bảng độc quyền.

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

VACUUM và autovacuum: cơ chế dọn bản chết tự động giữ PostgreSQL sống sót

Bloat (bài trước) sẽ bóp nghẹt database nếu không được dọn — và VACUUM là công cụ dọn đó. Bài này đo thật trên pg-lab: autovacuum TỰ chạy khi dead tuple vượt ngưỡng, đưa n_dead_tup từ 10.000 về 0 mà không cần một lệnh nào. Xem VACUUM VERBOSE báo cáo dọn 5000 tuple, không gian được tái dùng giữ kích thước ổn định, và vì sao đừng bao giờ tắt autovacuum.