Blocking: وقتی یک تراکنش پشت تراکنش دیگر منتظر میماند
در درس قبل دیدیم وقتی Session A روی یک ردیف قفل انحصاری دارد، Session B باید منتظر بماند. این وضعیت انتظار، اسم دارد: Blocking. خودِ Blocking یک باگ نیست — بخش طبیعی و لازم هر پایگاهدادهی چندکاربره است. مشکل از جایی شروع میشود که این انتظار، خیلی طول بکشد.
سناریوی کامل Blocking
اگر Session A به هر دلیلی — کدنویسی ضعیف، فراخوانی یک سرویس خارجی کند وسط تراکنش، یا فراموشکردن COMMIT — دیر تمام شود، Session B (و هر Session دیگری که منتظر همان ردیف است) هم به همان اندازه معطل میماند. این دقیقاً همان چیزی است که کاربران بهعنوان «سایت/اپلیکیشن قفل کرده» تجربه میکنند.
Blocking در برابر Deadlock — یک تفاوت مهم
چطور Blocking را کاهش دهیم
- تراکنشها را کوتاه نگه دار: هیچوقت وسط یک تراکنش، منتظر یک فراخوانی شبکهای یا کاربر نمان.
- ایندکس مناسب داشته باش: پرسوجوی بدون ایندکس مناسب، ممکن است مجبور شود ردیفهای بیشتری را قفل کند (موضوع فصل ۱۰).
- سطح ایزولهسازی مناسب انتخاب کن: بعضی سطوح ایزولهسازی، قفل کمتری میگیرند — موضوع دقیق درس بعدی.
- ابزار تشخیص: در SQL Server واقعی،
sp_who2یا Activity Monitor نشان میدهند کدام Session، کدام Session دیگر را مسدود کرده.
پیدا کردن Session مسدودکننده
در SQL Server واقعی، این پرسوجو نشان میدهد چه کسی منتظر چه کسی است:
SELECT r.session_id, r.blocking_session_id, -- کسی که قفل را نگه داشته r.wait_type, r.wait_time, DB_NAME(r.database_id) AS DatabaseName, t.text AS RunningSql FROM sys.dm_exec_requests r CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) t WHERE r.blocking_session_id <> 0;
ستون blocking_session_id شمارهی Session مقصر را میدهد. با دستور زیر قدیمیترین تراکنش باز پایگاهدادهی فعلی را هم میبینی:
DBCC OPENTRAN;
چه کار کنیم؟
| گام | اقدام |
|---|---|
| ۱ | ابتدا بفهم تراکنش مسدودکننده چه میکند (RunningSql و کاربر/برنامه). |
| ۲ | اگر کار مشروع است و بهزودی تمام میشود، صبر کن. |
| ۳ | اگر تراکنش رها شده (مثلاً برنامه فراموش کرده COMMIT کند)، از صاحب برنامه بخواه آن را ببندد. |
| ۴ | در آخرین راه و با هماهنگی، KILL 53; (شمارهی Session) تراکنش را Rollback میکند. |
KILL تراکنش را Rollback میکند و ممکن است Rollback خودش زمانبر باشد. آن را فقط وقتی استفاده کن که از اثرش مطمئنی.اگر کندی کلی سرور را بررسی میکنی، مقالهی چرا SQL Server کند شده است؟ بررسی Blocking را در کنار CPU، حافظه و دیسک توضیح داده است.
جمعبندی این درس
- Blocking یعنی یک تراکنش منتظر رهاشدن قفل تراکنش دیگر بماند — پدیدهای طبیعی، نه یک باگ.
- مشکل واقعی وقتی شروع میشود که تراکنش نگهدارندهی قفل، بیشازحد طول بکشد.
- Deadlock حالت خاصتری است: دو تراکنش منتظر یکدیگرند و SQL Server باید یکی را قربانی کند.
- کوتاه نگهداشتن تراکنشها، مؤثرترین راه کاهش Blocking است.
در آخرین درس این فصل، سراغ سطوح ایزولهسازی میرویم: چطور میتوان با تنظیم دقیقتر، بین سرعت و امنیت داده در برابر تداخل همزمان، تعادل برقرار کرد.
تمرینهای خودآزمایی
اول خودت جواب بده، بعد پاسخ را باز کن و مقایسه کن.
۱Blocking و Deadlock چه فرقی دارند؟نمایش پاسخ
Blocking انتظار موقت یک تراکنش برای دیگری است؛ Deadlock انتظار چرخهای است که SQL Server با قربانیکردن یکی از تراکنشها آن را میشکند.
۲چطور تراکنش مسدودکننده را پیدا کنیم؟نمایش پاسخ
ستون blocking_session_id در sys.dm_exec_requests یا دستور sp_who2.