# SQL Server Isolation Levels & Concurrency
Hai request cùng đọc `Stock = 1`. Cả hai cùng thấy còn hàng và cùng redeem thành công. Đây không còn là validation problem đơn thuần mà là **concurrency problem**.
## Dirty Read
Transaction A cập nhật nhưng chưa commit:
“`text
Balance = 1000
Update -> 500
Not committed
“`
Transaction B đọc được `500`.
Sau đó A rollback về `1000`.
B đã đọc dữ liệu chưa từng thực sự được commit.
## Non-repeatable Read
Transaction A:
“`sql
SELECT Balance
FROM Accounts
WHERE Id = 1;
— 1000
“`
Transaction B:
“`sql
UPDATE Accounts
SET Balance = 500
WHERE Id = 1;
COMMIT;
“`
Transaction A đọc lại và nhận `500`.
## Phantom Read
Transaction A:
“`sql
SELECT *
FROM Orders
WHERE Amount > 1000;
“`
Lần đầu có 10 rows. Transaction B insert thêm một row phù hợp điều kiện. A query lại thấy 11 rows.
## Lost Update
Hai request cùng đọc:
“`text
Stock = 10
“`
A tính `9`, B cũng tính `9`, rồi cả hai ghi `9`.
Kết quả đúng đáng lẽ phải là `8`.
## Isolation Levels
### READ UNCOMMITTED
“`sql
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
“`
Cho phép đọc uncommitted data.
`NOLOCK` thường có behavior tương tự:
“`sql
SELECT *
FROM Orders WITH (NOLOCK);
“`
`NOLOCK` không phải performance miễn phí. Bạn đánh đổi consistency để giảm locking.
### READ COMMITTED
Là isolation level mặc định phổ biến của SQL Server.
Ngăn dirty read nhưng vẫn có thể gặp non-repeatable read và phantom read.
### REPEATABLE READ
Giữ shared lock lâu hơn để ngăn row đã đọc bị thay đổi trong transaction.
Trade-off là blocking cao hơn.
### SERIALIZABLE
Mạnh nhất theo locking-based model.
Ngăn:
– Dirty Read
– Non-repeatable Read
– Phantom Read
Nhưng đổi lại có thể tăng blocking, giảm throughput và tăng deadlock risk.
### SNAPSHOT
Snapshot sử dụng row versioning.
Reader có thể đọc một version phù hợp thay vì phải chờ writer release lock.
“`text
Version 1 -> Balance = 100
Version 2 -> Balance = 80
“`
Transaction bắt đầu trước Version 2 có thể tiếp tục nhìn thấy Version 1.
## READ_COMMITTED_SNAPSHOT
“`sql
ALTER DATABASE MyDatabase
SET READ_COMMITTED_SNAPSHOT ON;
“`
Khi bật:
– `READ COMMITTED` dùng row versioning cho reads
– giảm reader/writer blocking
– tăng concurrency
Trade-off là version-store overhead và read semantics thay đổi.
## ALLOW_SNAPSHOT_ISOLATION
“`sql
ALTER DATABASE MyDatabase
SET ALLOW_SNAPSHOT_ISOLATION ON;
“`
Application sau đó có thể dùng:
“`sql
SET TRANSACTION ISOLATION LEVEL SNAPSHOT;
“`
Khác biệt cần nhớ:
“`text
READ_COMMITTED_SNAPSHOT
-> thay behavior của READ COMMITTED
ALLOW_SNAPSHOT_ISOLATION
-> cho phép transaction explicitly dùng SNAPSHOT
“`
## Interview questions
### What is SQL Server’s default isolation level?
> Read Committed is the traditional default isolation level in SQL Server.
### Why not use Serializable everywhere?
> Because stronger isolation reduces concurrency and increases locking, blocking, and deadlock risk. The isolation level should match the business consistency requirement.
## Key takeaways
Isolation level không phải càng cao càng tốt. Nó là trade-off giữa:
“`text
Consistency
vs
Concurrency
vs
Performance
“`
**Next:** Part 3 — Locking, Blocking & Deadlocks