Sau khi biết cách giảm Lock Contention, bài này bắt đầu giới thiệu 2 chiến lược khóa dữ liệu khi nhiều thread cùng truy cập tài nguyên dùng chung:

1. Pessimistic Locking  ← bài này
2. Optimistic Locking   ← bài tiếp theo

Tổng quan

                 Shared Data
                     │
      Multiple Threads Access
                     │
                     ▼
          Need Synchronization
                     │
       ┌─────────────┴──────────────┐
       ▼                            ▼
Pessimistic Locking        Optimistic Locking
 (Khóa trước, làm sau)     (Làm trước, kiểm tra sau)

Khi nào cần Lock?

Ví dụ hệ thống E-commerce — nhiều người cùng mua một sản phẩm:

Inventory: iPhone — Stock = 5

User A: Buy iPhone ─┐
                    ├──► cả hai đọc Stock = 5
User B: Buy iPhone ─┘     → cả hai trừ xuống
                          → Database bị sai ❌

Đây gọi là Data Corruption — dữ liệu bị sai do không đồng bộ.


Ý tưởng của Pessimistic Locking

Pessimistic = Luôn giả định sẽ có xung độtKhóa ngay từ đầu.


Luồng xử lý

Begin Transaction
      │
      ▼
SELECT ... FOR UPDATE   ← Lock ngay khi đọc
      │
      ▼
Record Locked
      │
      ▼
Business Logic (check inventory, pricing, discount...)
      │
      ▼
UPDATE inventory SET quantity = quantity - 1
      │
      ▼
COMMIT
      │
      ▼
Release Lock   ← chỉ unlock sau khi commit

Lock được giữ từ đầu transaction đến cuối transaction.


Các bước chi tiết

Bước 1 — Begin Transaction:

BEGIN;

Bước 2 — Đọc và khóa ngay:

SELECT * FROM inventory
WHERE product_id = 10
FOR UPDATE;

FOR UPDATE yêu cầu Database khóa record này — không thread nào khác được đọc/ghi cho đến khi COMMIT.

Bước 3 — Business Logic (toàn bộ diễn ra trong khi record đang bị khóa):

Check inventory → Pricing → Discount → Promotion → Shipping → Tax

Bước 4 — Update:

UPDATE inventory SET quantity = quantity - 1;
-- 500 → 499

Bước 5 — Commit và release lock:

COMMIT;
-- Database tự động release lock

Timeline nhiều thread

Time ──────────────────────────────────────────────────────►

Thread A   LOCK═══════════════════════════════UNLOCK
Thread B        ·············WAIT·············RUN
Thread C                          ·····WAIT·········RUN

Luôn chỉ có 1 thread được cập nhật Inventory tại một thời điểm:

             Inventory Record
                    │
               Record Locked
                    │
         ┌──────────┼──────────┐
         ▼          ▼          ▼
      Thread A   Thread B   Thread C
      Running    Waiting    Waiting

Long Transaction — điểm cần chú ý

Lock được giữ trong suốt toàn bộ quá trình:

BEGIN → LOCK → Read → Business Logic → Update → COMMIT → UNLOCK
               └────────────────────────────────┘
                        Long Lock Duration

Nếu Business Logic phức tạp (pricing, discount, promotion, shipping, tax…), lock có thể bị giữ rất lâu → các thread khác phải xếp hàng chờ → Contention tăng.


Ưu & nhược điểm

  Chi tiết
Ưu điểm Không bị Lost Update, không Data Corruption, đảm bảo Consistency, đơn giản để hiểu
Nhược điểm Lock giữ lâu → nhiều thread phải chờ → Queue → Contention → Throughput giảm

Khi nào nên dùng?

Pessimistic Locking phù hợp khi Contention rất cao.

High Contention
      │
Many Threads access Same Record
      │
Conflict Almost Certain
      │
→ Pessimistic Locking ✅

Các use case điển hình:

  • Flash Sale
  • Đặt vé máy bay / concert
  • Đặt phòng khách sạn
  • Mua sản phẩm số lượng giới hạn

Quy trình đầy đủ

                 Begin Transaction
                         │
                         ▼
          SELECT ... FOR UPDATE
                         │
                         ▼
                 Record Locked
                         │
                         ▼
              Business Processing
          (check, pricing, discount...)
                         │
                         ▼
             UPDATE Inventory
                         │
                         ▼
                   COMMIT
                         │
                         ▼
                Release Lock
                         │
                         ▼
         Next Waiting Thread Executes

Tổng kết

Đặc điểm Pessimistic Locking
Thời điểm khóa Ngay khi đọc dữ liệu (SELECT ... FOR UPDATE)
Thời gian giữ lock Từ đầu transaction đến COMMIT
Thread khác Bị block và phải chờ
Mức độ contention phù hợp Rất cao
Ưu điểm An toàn, tránh Data Corruption và Lost Update
Nhược điểm Lock giữ lâu, dễ tạo Queue và Lock Contention

Nếu gần như chắc chắn sẽ xảy ra xung đột, hãy khóa ngay từ đầu. Bài tiếp theo giới thiệu Optimistic Locking — cách tiếp cận ngược lại: không khóa trước, chỉ kiểm tra xung đột khi cập nhật.