Chương 13 — Anti-pattern & Khi nào PostgreSQL không phù hợp

Level 5. Chương kết. Phần một: các cách dùng sai lặp đi lặp lại — mỗi cái là một chương lý thuyết bị vi phạm. Phần hai: ranh giới kiến trúc thật sự của PostgreSQL — nơi vấn đề không phải “dùng sai” mà là “chọn sai công cụ”. Phần 1 — Anti-patterns Mỗi anti-pattern dưới đây đều có chung cấu trúc: tiện trước mắt → vi phạm một cơ chế nội tại → trả giá trễ và trả bằng lãi kép. ...

July 11, 2026 · 8 min

Chương 12 — Production Failure Cases: 21 hồ sơ sự cố

Level 5. Mỗi case theo khuôn: Triệu chứng → Root cause → Bên trong PostgreSQL → Điều tra (metric/log/lệnh) → Khắc phục → Phòng tránh. Các case tham chiếu ngược về chương lý thuyết tương ứng — chương này đồng thời là bài tổng ôn. Dashboard nền khuyến nghị (dùng chung cho mọi case): wait events theo thời gian (pg_stat_activity), TPS + p99 latency, connections theo state, dead tuples + last_(auto)vacuum các bảng top, WAL bytes/s + checkpoint timeline, replication lag byte, disk %util + fsync latency, cache hit ratio, max(age(datfrozenxid)). ...

July 11, 2026 · 13 min

Chương 11 — Checkpoint, Recovery, Replication

Level 3–5. Chương 5 hứa: “crash không mất gì, WAL dựng lại được”. Chương này trả nghĩa vụ chứng minh — và mở rộng cùng cơ chế đó thành PITR và replication: ba tính năng, một nền tảng duy nhất là WAL replay. 1. Problem Statement Crash recovery: sau mất điện, dựng lại trạng thái đã commit — tự động, không thao tác tay, thời gian đoán được. Backup/PITR: “khôi phục về 14:59, ngay trước câu DELETE nhầm lúc 15:00” — backup định kỳ thuần túy không làm nổi. Replication: bản sao nóng, trễ mili giây, đọc được — và failover khi primary chết. Cả ba là cùng một bài toán: tái tạo trạng thái từ (một ảnh chụp cũ) + (dòng WAL). Ai kiểm soát điểm dừng replay, người đó có tính năng tương ứng: dừng ở cuối WAL = crash recovery; dừng ở timestamp = PITR; không bao giờ dừng = replica. ...

July 11, 2026 · 9 min

Chương 10 — VACUUM, HOT, Freeze, Wraparound

Level 3–5. MVCC vay nợ: mỗi UPDATE/DELETE để lại rác, mỗi transaction đốt một XID hữu hạn. VACUUM là bộ máy trả nợ. Vận hành PostgreSQL nghiêm túc = vận hành VACUUM nghiêm túc. Chương này là chương “đáng tiền” nhất với người trực production. 1. Problem Statement — ba món nợ của MVCC Dead tuple: version cũ không còn snapshot nào cần (Chương 6). Không dọn → bảng/index phình, cache loãng, scan chậm. Không gian XID hữu hạn: XID 32 bit so sánh vòng tròn. Tuple mang xmin quá già (cách hiện tại >2³¹) sẽ bị phép so sánh hiểu ngược thành “tương lai” → dữ liệu committed biến mất. Phải “đóng băng” (freeze) tuple già trước khi điều đó xảy ra. Thống kê & Visibility Map lạc hậu: planner cần ANALYZE; index-only scan cần VM được cập nhật. VACUUM giải cả ba. Nếu bỏ VACUUM? — không phải “chậm dần” mà là dừng hẳn: đầy disk vì bloat, rồi trước cả đó, cluster tự khóa ghi để chống wraparound. Không có lựa chọn “không vacuum”, chỉ có “vacuum có kiểm soát” hoặc “vacuum lúc 3h sáng theo lệnh của PostgreSQL”. ...

July 11, 2026 · 10 min

Chương 9 — Index Internals: B-tree, Hash, GIN, GiST, BRIN

Level 4. Index là cấu trúc dữ liệu trên disk — nghĩa là mọi thiết kế của nó bị chi phối bởi page 8KB, WAL, MVCC và concurrency. Chương này mở nắp từng loại. 1. Problem Statement Heap không có thứ tự (Chương 3): tìm WHERE email='x@y.vn' = đọc toàn bộ bảng, O(N) page. Bảng 100GB → ~13 giây chỉ riêng I/O tuần tự, mỗi query. Cần cấu trúc phụ ánh xạ giá trị → ctid với chi phí tra cứu ~O(log N) tính bằng số page (không phải số phần tử — mỗi page là một lần I/O tiềm năng). ...

July 11, 2026 · 9 min

Chương 8 — Query Processing: từ SQL text đến thao tác trên Page

Level 4. SQL là ngôn ngữ khai báo: bạn nói cần gì, không nói làm thế nào. Toàn bộ chương này là câu chuyện PostgreSQL biến “cần gì” thành “làm thế nào” — và tại sao đôi khi nó chọn sai. 1. Problem Statement SELECT c.name, sum(o.amount) FROM customers c JOIN orders o ON o.customer_id = c.id WHERE c.region = 'APAC' AND o.created_at > now() - interval '30 days' GROUP BY c.name; Câu này có thể thực thi theo hàng nghìn cách: quét bảng nào trước, dùng index nào, join bằng thuật toán nào, group bằng hash hay sort. Chênh lệch giữa plan tốt nhất và tệ nhất trên dữ liệu lớn: 10⁴–10⁶ lần. Không tầng nào khác của database tạo ra chênh lệch hiệu năng lớn như planner. ...

July 11, 2026 · 10 min

Chương 7 — Lock Manager

Level 3. MVCC loại bỏ xung đột reader–writer. Phần còn lại — writer–writer, DDL, và bảo vệ cấu trúc trong bộ nhớ — thuộc về ba tầng lock của PostgreSQL. Đa số sự cố “database treo” trong production là sự cố lock, không phải sự cố I/O. 1. Problem Statement Ba lớp bài toán tranh chấp khác nhau về bản chất và thang thời gian: Micro (nanô giây): hai CPU cùng sửa một biến trong shared memory (refcount của buffer). Cần loại trừ trong vài chục chu kỳ CPU. Meso (micro giây): một backend sửa nội dung page trong khi backend khác đọc. Cần read/write lock ngắn. Macro (mili giây → giờ): hai transaction cùng UPDATE một row; ALTER TABLE trong khi query đang chạy. Cần lock theo ngữ nghĩa transaction: có hàng đợi, có phát hiện deadlock, tự nhả khi commit. Một cơ chế duy nhất không phục vụ nổi cả ba (lock có hàng đợi + deadlock detection quá đắt cho việc tăng một biến đếm). PostgreSQL xây ba tầng: ...

July 11, 2026 · 10 min

Chương 6 — Transaction Engine: MVCC, Snapshot, Visibility

Level 3. MVCC là quyết định thiết kế trung tâm của PostgreSQL. Hiểu nó là hiểu được: tại sao reader không block writer, tại sao có dead tuple, tại sao có VACUUM, tại sao “idle in transaction” là kẻ giết hệ thống thầm lặng. 1. Problem Statement 1.000 transaction đồng thời trên cùng bảng. Yêu cầu Isolation: mỗi transaction thấy database như một ảnh chụp nhất quán, không thấy thay đổi dở dang của người khác. ...

July 11, 2026 · 10 min

Chương 5 — WAL: Write-Ahead Log

Level 3. WAL là phát minh quan trọng nhất của ngành database (ARIES, 1992). Nó là lý do PostgreSQL dám giữ dirty page trong RAM, là nền của recovery, replication, PITR — và là nguồn của một nửa số sự cố production về disk. 1. Problem Statement Chương 1 xác lập hai sự thật vật lý mâu thuẫn nhau: Durability đòi hỏi fsync trước khi báo commit — mà fsync đắt (~0.1–1ms NVMe, ~10ms HDD). Thay đổi của một transaction rải rác trên nhiều page (heap, nhiều index, toast) — fsync tất cả các page đó mỗi commit = nhiều random write + nhiều fsync → vài chục ms mỗi commit → throughput chết. Thêm bài toán thứ ba: page 8KB > sector atomic 4KB → crash giữa lúc ghi page tạo torn page — nửa mới nửa cũ, checksum sai, không dùng được. ...

July 11, 2026 · 10 min

Chương 4 — Buffer Manager

Level 2. Disk chậm hơn RAM ~1000 lần. Buffer Manager là tầng quyết định PostgreSQL chạy ở tốc độ RAM hay tốc độ disk — tức là quyết định 90% cảm nhận hiệu năng. 1. Problem Statement Mỗi thao tác đọc/ghi tuple đều cần page 8KB tương ứng. Nếu mỗi lần đều read()/write() xuống disk: một query đọc 1 triệu tuple rải trên 100k page × ~100µs/lần đọc NVMe = 10 giây thuần I/O — trong khi từ RAM mất ~50ms. ...

July 11, 2026 · 10 min

Chương 3 — Physical Storage: Page, Tuple, TOAST, FSM, Visibility Map

Level 2. Đây là chương nền tảng nhất của bộ tài liệu. Hiểu từng byte của heap page là hiểu được một nửa PostgreSQL: MVCC, VACUUM, HOT, bloat, index — tất cả đều quy về đây. 1. Problem Statement Bảng orders 200GB phải nằm trên disk sao cho: Tìm một order theo con trỏ mất đúng 1 lần đọc disk. Thêm order mới không phải dịch chuyển dữ liệu cũ. Nhiều version của một row (MVCC) cùng tồn tại được. Crash giữa chừng không phá cấu trúc. Cột note dài 1MB không làm hỏng hiệu quả của các cột 8 byte bên cạnh. Nếu tổ chức sai tầng này: mọi thao tác đọc thành O(n), UPDATE phải rewrite file, crash để lại file rác. Toàn bộ chương này là câu trả lời của PostgreSQL cho bài toán đó. ...

July 11, 2026 · 13 min

Chương 2 — Kiến trúc tổng thể: Process & Shared Memory

Level 1–2. PostgreSQL là một “hệ điều hành thu nhỏ”: có process quản lý, có bộ nhớ chia sẻ, có scheduler nền, có cơ chế phục hồi. Chương này vẽ bản đồ toàn bộ hệ thống đó. 1. Problem Statement Một database server phải đồng thời: phục vụ hàng trăm connection, ghi dữ liệu nền, dọn rác, đồng bộ replica, thu thập thống kê — mà một thành phần chết không được kéo sập dữ liệu. Bài toán: tổ chức các đơn vị thực thi (process/thread) và bộ nhớ chung như thế nào để vừa cô lập lỗi, vừa chia sẻ trạng thái hiệu quả? ...

July 11, 2026 · 12 min

Chương 1 — Database Fundamentals: từ First Principles

Level 1. Trước khi nói về PostgreSQL, phải trả lời câu hỏi gốc: tại sao phần mềm quản lý dữ liệu lại khó đến mức cần một engine hàng triệu dòng code? 1. Problem Statement Mọi hệ thống phần mềm đều quy về một bài toán: nhận dữ liệu, lưu dữ liệu, trả lại dữ liệu đúng. Một hệ thống thanh toán nhận lệnh chuyển 500.000đ từ tài khoản A sang B. Yêu cầu nghe đơn giản: ...

July 11, 2026 · 12 min

PostgreSQL Internals — Bên dưới lớp SQL

Bộ tài liệu chuyên sâu về cách PostgreSQL hoạt động bên dưới lớp SQL và Storage, viết cho Backend Engineer, Database Engineer và Software Architect. Tài liệu này KHÔNG phải là gì Đây không phải tài liệu dạy SQL. Không có CREATE TABLE ở chương mở đầu. Không giải thích cú pháp. Đây là tài liệu giúp bạn hiểu PostgreSQL như một hệ điều hành thu nhỏ dành cho dữ liệu: cách nó tổ chức bộ nhớ, quản lý page, lưu tuple, điều phối transaction, ghi WAL, phục hồi sau sự cố, tối ưu truy vấn, và phối hợp với OS để đạt hiệu năng và độ tin cậy. ...

July 11, 2026 · 4 min

4 Nguyên Tắc Vàng Khi Dùng Index Mà Mình Ước Gì Biết Sớm Hơn

Chào mọi người, trong quá trình làm việc với database, mình thấy rất nhiều trường hợp không hiểu rõ bản chất của index dẫn đến không sử dụng index một cách hiệu quả. Hôm nay, tranh thủ dịp lễ 1/5 không được đi chơi, ở nhà thôi thì ngồi viết một bài blog về vấn đề này vậy. (Lưu ý: Bài viết mình có tham khảo AI sau khi viết để chỉnh chu lại văn phong và ngữ pháp cũng như là verify lại kiến thức của mình nhé, nào gét gô) ...

May 1, 2026 · 13 min

PostgreSQL xử lý câu lệnh DML như thế nào?

Khi làm việc với database chắc hẳn chúng ta đã quen với các câu lệnh như SELECT, UPDATE, INSERT, DELETE,… Giả sử khi chạy một câu lệnh INSERT INTO ... để thêm record vào DB thì bên trong cơ sở dữ liệu sẽ làm những gì để xử lý? Trong bài viết này, hãy cùng mình tìm hiểu đằng sau một câu lệnh SQL khi thực thi sẽ đi qua những bước gì nhé. ...

September 7, 2025 · 6 min