# Optimistic vs Pessimistic Concurrency in EF Core

Giả sử coupon chỉ còn:

“`text
Stock = 1
“`

User A và User B cùng đọc `1`. Nếu cả hai cùng redeem thành công, business invariant đã bị phá vỡ.

Đây là bài toán concurrency.

## Optimistic Concurrency

Optimistic concurrency giả định conflict xảy ra không thường xuyên.

Ví dụ:

“`text
Version = 5
“`

Update:

“`sql
UPDATE Events
SET Status = @status,
Version = Version + 1
WHERE Id = @id
AND Version = 5;
“`

Nếu:

“`text
0 rows affected
“`

nghĩa là data có thể đã bị thay đổi bởi transaction khác.

## EF Core Concurrency Token

Ví dụ:

“`csharp
public class Event
{
public Guid Id { get; set; }

public string Status { get; set; }

[Timestamp]
public byte[] RowVersion { get; set; }
}
“`

Khi conflict xảy ra EF Core có thể throw:

“`text
DbUpdateConcurrencyException
“`

## Không nên catch rồi ignore

Các strategy phổ biến:

### Client Wins

Overwrite database bằng data client.

### Database Wins

Bỏ thay đổi client và reload database state.

### Merge

So sánh các field và merge theo business rule.

Strategy nào đúng phụ thuộc business requirement.

## Pessimistic Concurrency

Pessimistic locking giả định conflict có khả năng cao.

Concept:

“`text
Lock first
Work
Commit
Release
“`

Ưu điểm:

– ngăn một số race conditions từ đầu

Nhược điểm:

– blocking
– deadlock
– throughput thấp hơn

## Optimistic vs Pessimistic

| | Optimistic | Pessimistic |
|—|—|—|
| Lock lâu | Không | Có |
| Throughput | Cao | Thấp hơn |
| Conflict handling | Sau khi xảy ra | Ngăn từ đầu |
| Phù hợp | Conflict hiếm | Conflict cao |

## Case: Last Coupon

Giả sử:

“`text
Stock = 1
“`

Hai user cùng redeem.

Một cách an toàn là atomic conditional update:

“`sql
UPDATE Coupons
SET Stock = Stock – 1
WHERE Id = @id
AND Stock > 0;
“`

Sau đó kiểm tra affected rows.

Nếu một row bị update:

“`text
success
“`

Nếu zero rows:

“`text
out of stock / already consumed
“`

## Interview questions

### Optimistic vs pessimistic concurrency?

> Optimistic concurrency allows transactions to proceed without long-lived locks and detects conflicts when updating. Pessimistic concurrency locks resources upfront to prevent conflicts but can cause blocking and deadlocks.

### What do you do with DbUpdateConcurrencyException?

> I don’t blindly ignore it. I determine whether the business operation can be retried, whether database state should win, or whether the conflict needs to be returned to the user.

## Key takeaways

Concurrency control không phải framework detail. Nó là business correctness problem.

Khi thiết kế một operation concurrent, hãy hỏi:

“`text
What invariant must never be broken?
“`

Sau đó chọn:

“`text
Atomic SQL operation
Optimistic concurrency
Pessimistic locking
Unique constraint
Isolation level
“`

phù hợp với invariant đó.

**End of Stage 1 — Database Fundamentals**