# ACID & Database Transactions for .NET Backend Engineers

Khi làm backend, nhiều lỗi nghiêm trọng không đến từ syntax hay framework mà đến từ **transaction boundary** không đúng. Một flow tưởng đơn giản như chuyển tiền, redeem coupon hoặc cập nhật wallet có thể làm dữ liệu sai nếu transaction không được thiết kế đúng.

## ACID là gì?

ACID gồm bốn thuộc tính cốt lõi của transaction:

### Atomicity

Một transaction phải **thành công toàn bộ hoặc rollback toàn bộ**.

“`sql
BEGIN TRY
BEGIN TRANSACTION;

UPDATE Accounts
SET Balance = Balance – 100
WHERE Id = 1;

UPDATE Accounts
SET Balance = Balance + 100
WHERE Id = 2;

COMMIT;
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0
ROLLBACK;

THROW;
END CATCH;
“`

Nếu bước thứ hai lỗi thì bước đầu tiên cũng phải rollback.

### Consistency

Database phải chuyển từ một trạng thái hợp lệ sang một trạng thái hợp lệ khác.

“`sql
ALTER TABLE Accounts
ADD CONSTRAINT CK_Accounts_Balance
CHECK (Balance >= 0);
“`

Consistency thường được bảo vệ bằng:

– Primary Key
– Foreign Key
– Unique Constraint
– Check Constraint
– Business rules
– Transaction logic

### Isolation

Isolation kiểm soát cách các transaction chạy đồng thời nhìn thấy và thay đổi dữ liệu của nhau.

Các vấn đề thường gặp:

– Dirty Read
– Non-repeatable Read
– Phantom Read
– Lost Update

### Durability

Sau khi transaction đã `COMMIT`, dữ liệu phải tồn tại kể cả khi process hoặc server gặp sự cố.

SQL Server sử dụng transaction log để hỗ trợ recovery.

## Transaction trong EF Core

Một lần gọi:

“`csharp
await dbContext.SaveChangesAsync();
“`

thường được EF Core thực hiện trong một transaction khi cần.

Nếu business flow gồm nhiều bước độc lập nhưng phải thành công cùng nhau:

“`csharp
await using var transaction =
await dbContext.Database.BeginTransactionAsync();

try
{
dbContext.Wallets.Update(wallet);
await dbContext.SaveChangesAsync();

dbContext.UserCoupons.Add(coupon);
await dbContext.SaveChangesAsync();

await transaction.CommitAsync();
}
catch
{
await transaction.RollbackAsync();
throw;
}
“`

## Khi nào cần explicit transaction?

Ví dụ:

“`text
Update Wallet
+ Create Coupon
+ Write Reward History
“`

Nếu ba bước phải thành công hoặc thất bại cùng nhau, chúng nên nằm trong cùng transaction.

Không nên giữ transaction mở khi:

“`text
Call external API
Send email
Wait for third-party service
Long-running computation
“`

Transaction càng dài thì lock càng lâu, blocking tăng và nguy cơ deadlock cao hơn.

## Database transaction không phải distributed transaction

Ví dụ:

“`text
Save Order in SQL
+
Publish message to Azure Service Bus
“`

Database có thể commit thành công nhưng publish message lại thất bại.

Kết quả:

“`text
Order exists
Message missing
“`

Đây là lý do các hệ thống distributed thường sử dụng pattern như **Transactional Outbox**.

## Interview questions

### What is ACID?

> ACID stands for Atomicity, Consistency, Isolation, and Durability. Atomicity ensures that a transaction either fully succeeds or fully rolls back. Consistency keeps the database in a valid state. Isolation controls how concurrent transactions interact. Durability ensures committed data survives failures.

### When would you use an explicit transaction in EF Core?

> I use an explicit transaction when multiple SaveChanges calls or related database operations must succeed or fail as one business operation.

## Key takeaways

– ACID là nền tảng của transaction reliability.
– Transaction boundary phải bám theo business operation.
– Giữ transaction ngắn.
– Database transaction không tự giải quyết consistency giữa database và message broker.

**Next:** Part 2 — Isolation Levels & Concurrency