Cơ sở dữ liệu 22/09/2026 6 phút

Transaction ID wraparound trong PostgreSQL: hiểm họa 32-bit và VACUUM freeze

Transaction id là số 32-bit, cửa sổ dùng được chỉ khoảng 2 tỉ. Nếu dòng cũ không được freeze trước khi bộ đếm tràn, chúng bỗng trông như tương lai và biến mất — thảm họa. Đo thật cách theo dõi age(datfrozenxid) và vì sao VACUUM bắt buộc kể cả bảng chỉ đọc. PostgreSQL 16.

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

VACUUM, bloat và wraparound đo thật: mười lần UPDATE toàn bảng biến 27 MB thành 296 MB, VACUUM giải phóng 90% chỗ nhưng không trả đĩa, autovacuum mặc định không chạy lần nào trong 60 giây tải, và một giao dịch mở giữ 600.000 dead tuple không dọn được

Đo trên PostgreSQL 16 với pgstattuple: bảng 200.000 dòng sau 10 UPDATE toàn bảng phình từ 27 MB lên 296 MB, VACUUM 599 ms đưa dead về 0,13% và free lên 90% nhưng kích thước giữ nguyên, VACUUM FULL 278 ms trả về 27 MB. Dưới pgbench 60 giây trên 3 triệu dòng, autovacuum mặc định chạy 0 lần và dead tuple lên 96.000; chỉnh scale 0.01, naptime 5 giây, cost_delay 0 thì chạy 4 lần. Một giao dịch mở 40 giây làm VACUUM báo 600.000 dead but not yet removable và bảng phình 108 lên 189 MB dù vacuum đều. Hạ freeze_max_age xuống 100.000 rồi đốt 160.000 XID: 773 lần aggressive vacuum giữ age dưới ngưỡng.