TGViewer
C# Geeks (.NET) C# Geeks (.NET) @csharpgeeks · 549 subscribers
Post #826 226
⚖️ ءOptimistic Locking vs Pessimistic Locking

فرض کن دو کاربر هم‌زمان موجودی یک کیف پول را تغییر می‌دهند.
موجودی اولیه:
Balance = 1000

کاربر اول می‌خواهد 700 تومان برداشت کند.
کاربر دوم هم‌زمان می‌خواهد 500 تومان برداشت کند.
اگر هر دو درخواست مقدار 1000 را بخوانند:
User A reads: 1000
User B reads: 1000

User A writes: 300
User B writes: 500

نتیجه:
Final Balance = 500

اما در واقع باید فقط یکی از برداشت‌ها موفق شود؛ چون موجودی برای هر دو کافی نیست.
این مشکل یکی از نمونه‌های معروف Race Condition و Lost Update است.
اینجا دو رویکرد مهم داریم:
Optimistic Locking
Pessimistic Locking


🟢 ءOptimistic Locking چیست؟
در Optimistic Locking فرض می‌کنیم برخورد هم‌زمانی معمولاً کم است.
پس هنگام خواندن داده، آن را قفل نمی‌کنیم.
به‌جای قفل‌کردن، هنگام ذخیره بررسی می‌کنیم:
آیا داده‌ای که من خواندم هنوز همان نسخه‌ی قبلی است؟

اگر در این فاصله شخص دیگری داده را تغییر داده باشد، عملیات شکست می‌خورد و باید:
دوباره داده را بخوانیم؛
تصمیم را از نو محاسبه کنیم؛
یا خطای Conflict به کاربر بدهیم.
مثال با Version
فرض کن رکورد حساب این‌طور است:
AccountId = 10
Balance = 1000
Version = 5

کاربر A رکورد را می‌خواند:
Balance = 1000
Version = 5

کاربر B هم همین نسخه را می‌خواند:
Balance = 1000
Version = 5

کاربر A ذخیره می‌کند:
UPDATE Accounts
SET Balance = 300,
Version = 6
WHERE AccountId = 10
AND Version = 5;

این Query موفق می‌شود.
حالا کاربر B می‌خواهد ذخیره کند:
UPDATE Accounts
SET Balance = 500,
Version = 6
WHERE AccountId = 10
AND Version = 5;

اما دیگر رکوردی با Version = 5 وجود ندارد.
پس:
Affected Rows = 0

یعنی:
داده در فاصله‌ی خواندن تا ذخیره تغییر کرده است.

این همان Optimistic Concurrency Conflict است.

🧠 نکته‌ی مهم
ءOptimistic Locking الزاماً به معنی استفاده از یک ستون به نام Version نیست.
می‌توان از موارد زیر هم استفاده کرد:
ءrowversion در SQL Server؛
ءTimestamp یا Version Number؛
مقدار Hash؛
بررسی مقدار قبلی چند ستون؛
شرط روی UpdatedAt؛
ءConcurrency Tokenء در EF Core.
اما برای تشخیص Conflict، باید یک مقدار قابل‌اعتماد برای مقایسه داشته باشیم.

🟦 ءOptimistic Locking
در SQL Server می‌توان از rowversion استفاده کرد:
public sealed class Account
{
public int Id { get; set; }

public decimal Balance { get; set; }

public byte[] RowVersion { get; set; } = [];
}

پیکربندی:
protected override void OnModelCreating(
ModelBuilder modelBuilder)
{
modelBuilder.Entity<Account>()
.Property(x => x.RowVersion)
.IsRowVersion();
}

حالا EF Core هنگام Update، مقدار RowVersion قبلی را در شرط قرار می‌دهد.
اگر شخص دیگری رکورد را تغییر داده باشد، EF Core معمولاً با این Exception مواجه می‌شود:
DbUpdateConcurrencyException

🔴 ءPessimistic Locking چیست؟
در Pessimistic Locking فرض می‌کنیم برخورد هم‌زمانی محتمل است.
پس از همان ابتدا داده را قفل می‌کنیم.
یعنی:
تا وقتی من در حال کار روی این رکورد هستم، دیگران نباید بتوانند آن را به شکل ناسازگار تغییر دهند.

مثلاً:
Transaction A:
Lock Account 10
Read Balance = 1000
Withdraw 700
Commit
Release Lock

Transaction B:
Wait for Account 10
Read Balance = 300
Withdraw 500
Reject

در این روش، کاربر دوم باید منتظر آزادشدن Lock بماند.
مثال SQL Server با UPDLOCK
یک الگوی رایج در SQL Server:
BEGIN TRANSACTION;

SELECT Balance
FROM Accounts WITH (UPDLOCK, ROWLOCK)
WHERE Id = 10;

-- Validate balance
-- Update balance

UPDATE Accounts
SET Balance = Balance - 700
WHERE Id = 10;

COMMIT;

ءUPDLOCK باعث می‌شود SQL Server هنگام خواندن، قفل Update بگیرد تا عملیات تغییر هم‌زمان کنترل شود.
اما باید دقت کرد:
ءLock تا پایان Transaction باقی می‌ماند؛
ءTransaction باید کوتاه باشد؛
ءLock طولانی می‌تواند باعث Blocking شود؛
چند Lock ناسازگار می‌توانند Deadlock ایجاد کنند.
🎯 مثال واقعی: ویرایش پروفایل کاربر
فرض کن دو کاربر یا دو Tab، پروفایل یک نفر را باز کرده‌اند.
نسخه‌ی اولیه:
Name = Milad
Version = 3

Tab A:
Name = Milad Heidarpour
Version = 3

Tab B:
Name = Milad Developer
Version = 3

اگر Tab A زودتر ذخیره کند:
Version = 4

Tab B دیگر نباید بی‌خبر تغییرات Tab A را Overwrite کند.
با Optimistic Locking:
Tab B → 409 Conflict

و UI می‌تواند بگوید:
این اطلاعات توسط کاربر دیگری تغییر کرده است. لطفاً داده‌ی جدید را بررسی کنید.
More from @csharpgeeks
  1. Sep 22, 2026یه مدتی قراره از دنیای NET. فاصله بگیرم، چون وقتشه برم سربازی. راستش نمیدونم این مدت رو چج…
  2. Sep 20, 2026🔥 حالا مشکل اصلی: Alert Storm فرض کن Database از دسترس خارج شده. ۱۰۰ Pod داری. هر Pod می‌…
  3. Sep 20, 2026🚨 طراحی سیستم Monitoring و Alerting در یک سیستم بزرگ فرض کن ساعت ۳ صبح است. سیستم شما با…
  4. Sep 19, 2026#Engineering_Leadership تصمیم نگرفتن هم یک تصمیم است یه چیز عجیب توی تیم‌های مهندسی: گاهی…
  5. Sep 19, 2026☑ چک‌لیست آماده‌سازی تیم، فرایندها و زیرساخت برای توسعه با AI توجه: هیچ چک‌لیستی جهان‌شمول…
  6. Sep 19, 2026📌پایان یک انتظار طولانی: اعتبارسنجی ناهمگام (Async Validation) در NET 11.
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →