Transaction Isolation Level - SERIALIZABLE
Đỉnh cao trong thế giới Isolation Level đó chính là SERIALIZABLE.
Nghe tên thôi đã thấy... lạnh gáy rồi 😎
Định nghĩa:
SERIALIZABLE = mọi transaction chạy như thể nó đang chạy lần lượt từng cái một, không ai chen vào.
Chuẩn luôn, không đùa đâu: SERIALIZABLE làm thế giới của ta an toàn như ngân hàng, nhưng bù lại, cũng đắt đỏ như ngân hàng vậy.
1. SERIALIZABLE là gì?
Nói ngắn gọn:
Không Dirty Read
Không Non-Repeatable Read
Không Phantom Read
Không Insert bậy, không Update lén, không Delete phũ.
Mọi transaction nhìn thấy y như là mình đang chạy một mình trên database này.
Không ai đẻ thêm bản ghi bất thình lình. Không ai bốc hơi bản ghi. Không ai sửa lén sau lưng.
Cảm giác?
“Mày vào quán gọi phở, nguyên cái quán đóng cửa phục vụ riêng mày.”
2. Tình huống dễ hiểu
Giả sử có bảng accounts:
| id | balance |
| 1 | 1000 |
| 2 | 2000 |
Transaction A:
START TRANSACTION;
SELECT SUM(balance) FROM accounts;
-- Thấy tổng tiền = 3000
Transaction B (ở ngoài):
INSERT INTO accounts (id, balance) VALUES (3, 5000);
COMMIT;
Nếu Isolation thấp (ví dụ READ COMMITTED), Transaction A sau đó:
SELECT SUM(balance) FROM accounts;
-- Thấy tổng tiền = 8000 (WTF??)
Nhưng nếu là SERIALIZABLE, thì:
Transaction B phải đợi Transaction A kết thúc mới được Insert.
Hoặc Transaction B bị lỗi (Serialization failure).
→ Không bao giờ có chuyện dữ liệu Transaction A đọc bị thay đổi giữa chừng.
3. Cách mà SERIALIZABLE "chơi đẹp"
Database khóa dữ liệu kỹ như ngân khố.
Hoặc dùng snapshot + validation: kiểm tra xem có ai phá bĩnh giữa chừng không.
Nếu có, Transaction fail liền! ("Serialization Error" quen thuộc nè)
4. Những lưu ý sống còn
| Câu hỏi | Trả lời |
| Dùng SERIALIZABLE có chậm không? | Chậm vãi. Vì nhiều transaction phải đợi nhau, hoặc bị fail, retry. |
| Có deadlock không? | Có, vì nhiều transaction ôm khóa chết chặt. |
| Khi nào mới nên xài? | Khi dữ liệu rất nhạy cảm (ví dụ: ngân hàng, chứng khoán) và không thể chịu được lỗi dù là nhỏ nhất. |
| Có cách nào bớt đau không? | Có. Xài SERIALIZABLE chỉ ở vài transaction cần độ chính xác tuyệt đối. Chứ để default vậy là database khóc đó. |
5. Ví dụ chiến đấu thực tế
Scenario:
Đếm số lượng đơn hàng giá > 500.
Transaction A:
START TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SELECT COUNT(*) FROM orders WHERE price > 500;
-- Thấy 10 đơn hàng
Transaction B:
INSERT INTO orders (id, price) VALUES (11, 600);
-- Bình thường => đẻ thêm một đơn thỏa điều kiện
Trong SERIALIZABLE, Transaction B sẽ:
Chờ Transaction A xong.
Hoặc bị lỗi:
ERROR: could not serialize access due to concurrent update.
→ Không bao giờ có vụ Transaction A thấy 10 đơn, mà lát sau thấy 11 đơn.
6. Tóm gọn
| Mức độ nguy hiểm | Trạng thái |
| Dirty Read | Không |
| Non-Repeatable Read | Không |
| Phantom Read | Không |
| Insert lén, Update phũ | Không |
| Hiệu năng | Rùa bò |
7. Nói nhỏ
Đừng bật SERIALIZABLE cho toàn bộ hệ thống Production (unless muốn server ngáp ngáp).
Chỉ dùng cho các transaction thật sự cần chính xác từng đồng xu.
Nên biết retry Transaction khi bị serialization error.
Chốt bài
SERIALIZABLE – đỉnh cao của cô đơn trong thế giới database.
Càng cô đơn, càng an toàn, càng mắc tiền.
Nhưng nhớ, xài đúng lúc thì nó cứu ta. Xài bừa bãi thì nó giết server ta.