آموزش sys.dm_os_latch_stats؛ تحلیل Latch Contention در SQL Server
Latch سازوکار همگامسازی سبک درون موتور SQL Server است که از ساختارهای حافظه و عملیات داخلی محافظت میکند. sys.dm_os_latch_stats زمان و تعداد انتظار را بر اساس Latch Class بهصورت تجمعی ارائه میدهد.
Latch با Lock یکسان نیست. Lock عمدتاً سازگاری منطقی تراکنشها را حفظ میکند، در حالی که Latch از ساختار فیزیکی یا داخلی طی عملیات کوتاه محافظت میکند. راهحل یک Lock Contention لزوماً برای Latch Contention مناسب نیست.
همچنین همه Page Latchها در این DMV به شکل مورد انتظار دیده نمیشوند و برای برخی خانوادهها باید Wait Statistics و ساختارهای دیگر را بررسی کرد. نام Latch Class جهت بررسی داخلی را مشخص میکند، نه اینکه بهتنهایی علت قطعی را اعلام کند.
شمارندهها از شروع سرویس یا آخرین Clear تجمع دارند. تحلیل حرفهای از Delta، تعداد درخواست، میانگین زمان و همبستگی با workload استفاده میکند.
این مقاله یکی از بخشهای راهنمای جامع Wait Statistics در SQL Server است و مثالها را از مشاهده پایه تا نمونهبرداری و نکات عملیاتی پیش میبرد.
DMV یک منبع شواهد است، نه نسخه درمان. بازه، Uptime، شدت بار و اثر کاربری را پیش از هر تصمیم ثبت کنید.
تعریف و کاربرد sys.dm_os_latch_stats
sys.dm_os_latch_stats برای آمار Latchهای داخلی موتور استفاده میشود. خروجی آن باید در کنار هدف تشخیص، نسخه SQL Server و Counterهای مکمل خوانده شود تا میان نشانه و علت ریشهای اشتباه نشود.
در محیط Production بهتر است Query مشاهدهای، محدود و قابل ثبت باشد. هر اقدام تغییردهنده مانند Reset Counter یا خاتمه Session باید جدا از مرحله مشاهده، با مجوز و برنامه بازگشت انجام شود.
نحو پایه
SELECT *
FROM sys.dm_os_latch_stats;
ستونها و معنای آنها
| ستون | توضیح |
|---|
| latch_class | کلاس داخلی Latch که ساختار یا مسیر محافظتشده را نشان میدهد. |
| waiting_requests_count | تعداد درخواستهایی که برای آن کلاس منتظر شدهاند. |
| wait_time_ms | کل زمان انتظار تجمعی بر حسب میلیثانیه. |
| max_wait_time_ms | بیشترین زمان یک انتظار ثبتشده برای کلاس. |
نوع خروجی و دامنه Counter
خروجی یک Rowset از Counterهای تجمعی است. مقادیر از زمان آغاز دامنه مربوط رشد میکنند و برای تحلیل بازهای باید دو Snapshot معتبر با زمان ثبتشده مقایسه شوند.
پیشنیاز دسترسی و ملاحظات نسخه
مشاهده DMVهای سطح سرور نیازمند مجوز مناسب است. در نسخههای قدیمی معمولاً VIEW SERVER STATE مطرح است و در SQL Server 2022 بسیاری از اطلاعات کارایی به VIEW SERVER PERFORMANCE STATE منتقل شدهاند. در Azure SQL و سرویسهای مدیریتشده، دامنه دید و نقش لازم ممکن است متفاوت باشد.
برای حفظ اصل کمترین دسترسی، مجوز را به حساب Collector یا نقش مانیتورینگ محدود کنید و دسترسی به متن Query را جداگانه ارزیابی نمایید. خروجی تشخیصی ممکن است نام کاربر، برنامه، Object یا متن حساس داشته باشد.
مثالهای عملی
مثال ۱: نمایش Latch Classهای دارای انتظار
این Query کلاسهای دارای زمان انتظار مثبت را از بیشترین مقدار مرتب میکند.
SELECT
latch_class,
waiting_requests_count,
wait_time_ms,
max_wait_time_ms
FROM sys.dm_os_latch_stats
WHERE wait_time_ms > 0
ORDER BY wait_time_ms DESC;
| ستون یا شاخص | خروجی نمونه |
|---|
| latch_class | wait_time_ms |
| ACCESS_METHODS_DATASET_PARENT | 48200 |
| BUFFER | 19300 |
نام کلاس نقطه شروع بررسی است و بدون Delta یا Context بار نباید به تغییر فوری منجر شود.
مثال ۲: ده کلاس با بیشترین تعداد انتظار
مرتبسازی بر اساس تعداد مشخص میکند کدام Latchها پرتکرارند، حتی اگر هر رخداد کوتاه باشد.
SELECT TOP (10)
latch_class,
waiting_requests_count,
wait_time_ms
FROM sys.dm_os_latch_stats
WHERE waiting_requests_count > 0
ORDER BY waiting_requests_count DESC;
| ستون یا شاخص | خروجی نمونه |
|---|
| latch_class | waiting_requests_count |
| BUFFER | 125000 |
| LOG_MANAGER | 28400 |
تعداد زیاد با میانگین بسیار کم ممکن است اثر کاربری محدودی داشته باشد.
مثال ۳: محاسبه میانگین زمان Latch
NULLIF تقسیم بر صفر را کنترل و میانگین هر درخواست منتظر را محاسبه میکند.
SELECT TOP (20)
latch_class,
waiting_requests_count,
CAST(wait_time_ms * 1.0 /
NULLIF(waiting_requests_count, 0) AS decimal(18,2)) AS avg_wait_ms
FROM sys.dm_os_latch_stats
WHERE wait_time_ms > 0
ORDER BY avg_wait_ms DESC;
| ستون یا شاخص | خروجی نمونه |
|---|
| latch_class | avg_wait_ms |
| FGCB_ADD_REMOVE | 18.42 |
| LOG_MANAGER | 2.11 |
میانگین را همراه max_wait_time_ms ببینید تا رخدادهای پرت پنهان نشوند.
مثال ۴: محاسبه سهم هر Latch Class
این گزارش سهم درصدی کلاسها از مجموع زمان Latch را نمایش میدهد.
WITH L AS
(
SELECT latch_class, wait_time_ms
FROM sys.dm_os_latch_stats
WHERE wait_time_ms > 0
), T AS
(
SELECT SUM(wait_time_ms) AS total_wait_ms FROM L
)
SELECT TOP (10)
L.latch_class,
CAST(100.0 * L.wait_time_ms /
NULLIF(T.total_wait_ms, 0) AS decimal(6,2)) AS wait_percent
FROM L
CROSS JOIN T
ORDER BY wait_percent DESC;
| ستون یا شاخص | خروجی نمونه |
|---|
| latch_class | wait_percent |
| ACCESS_METHODS_DATASET_PARENT | 44.30 |
| BUFFER | 17.75 |
در بار کم درصد بالا میتواند از چند میلیثانیه ساخته شود؛ مقدار مطلق را حذف نکنید.
مثال ۵: فیلتر یک Latch Class مشخص
پارامتر Unicode برای تمرکز روی کلاسی که در Baseline غیرعادی شده بهکار میرود.
DECLARE @LatchClass nvarchar(120) = N'BUFFER';
SELECT
latch_class,
waiting_requests_count,
wait_time_ms,
max_wait_time_ms
FROM sys.dm_os_latch_stats
WHERE latch_class = @LatchClass;
| ستون یا شاخص | خروجی نمونه |
|---|
| latch_class | max_wait_time_ms |
| BUFFER | 122 |
اگر ردیفی وجود نداشت، نام کلاس و تفاوت نسخه را بررسی کنید؛ مقدار فرضی نسازید.
مثال ۶: یافتن کلاسهای با حداکثر انتظار غیرعادی
شرط آستانه، کلاسهایی را که حداقل یک رخداد طولانی داشتهاند جدا میکند.
DECLARE @MaxWaitThresholdMs bigint = 1000;
SELECT
latch_class,
max_wait_time_ms,
wait_time_ms,
waiting_requests_count
FROM sys.dm_os_latch_stats
WHERE max_wait_time_ms >= @MaxWaitThresholdMs
ORDER BY max_wait_time_ms DESC;
| ستون یا شاخص | خروجی نمونه |
|---|
| latch_class | max_wait_time_ms |
| FGCB_ADD_REMOVE | 3140 |
آستانه را از SLA و Baseline بسازید، نه از یک عدد ثابت در همه سرورها.
مثال ۷: ثبت Snapshot آغاز بازه
Snapshot اول پایه محاسبه Delta تعداد و زمان انتظار در بازه بار است.
DROP TABLE IF EXISTS #LatchStart;
SELECT
latch_class,
waiting_requests_count,
wait_time_ms,
max_wait_time_ms
INTO #LatchStart
FROM sys.dm_os_latch_stats;
SELECT COUNT(*) AS captured_classes
FROM #LatchStart;
| ستون یا شاخص | خروجی نمونه |
|---|
| captured_classes | وضعیت |
| 154 | Snapshot ثبت شد |
برای تحلیل دائمی زمان UTC، نام سرور و Uptime را نیز در جدول مخزن اضافه کنید.
مثال ۸: محاسبه Delta کلاسهای Latch
پس از بازه کاری، اختلاف Counterهای جاری با Snapshot اول محاسبه و مرتب میشود.
SELECT TOP (15)
C.latch_class,
C.wait_time_ms - B.wait_time_ms AS delta_wait_ms,
C.waiting_requests_count - B.waiting_requests_count AS delta_requests
FROM sys.dm_os_latch_stats AS C
INNER JOIN #LatchStart AS B
ON B.latch_class = C.latch_class
WHERE C.wait_time_ms >= B.wait_time_ms
ORDER BY delta_wait_ms DESC;
| ستون یا شاخص | خروجی نمونه |
|---|
| latch_class | delta_wait_ms |
| BUFFER | 8250 |
| LOG_MANAGER | 2190 |
کاهش Counter نشانه Reset یا Restart است و بازه باید نامعتبر علامتگذاری شود.
مثال ۹: ثبت Snapshot زماندار برای گزارش سازمانی
این مثال داده را با زمان UTC و نام سرور آماده انتقال به مخزن مانیتورینگ میکند.
DROP TABLE IF EXISTS #LatchSnapshot;
SELECT
SYSUTCDATETIME() AS captured_at_utc,
@@SERVERNAME AS server_name,
latch_class,
waiting_requests_count,
wait_time_ms,
max_wait_time_ms
INTO #LatchSnapshot
FROM sys.dm_os_latch_stats;
SELECT TOP (5) *
FROM #LatchSnapshot
ORDER BY wait_time_ms DESC;
| ستون یا شاخص | خروجی نمونه |
|---|
| server_name | latch_class |
| SQL-PROD-01 | BUFFER |
Retention را طوری تنظیم کنید که روند بلندمدت بماند ولی حجم بدون هدف رشد نکند.
مثال ۱۰: پاکسازی کنترلشده Latch Stats
DBCC SQLPERF Counterهای این DMV را Reset میکند و باید فقط در سناریوی برنامهریزیشده اجرا شود.
-- پیش از اجرا Snapshot و تأیید عملیاتی بگیرید.
DBCC SQLPERF(N'sys.dm_os_latch_stats', CLEAR);
SELECT SUM(wait_time_ms) AS latch_wait_after_clear
FROM sys.dm_os_latch_stats;
| ستون یا شاخص | خروجی نمونه |
|---|
| latch_wait_after_clear | تفسیر |
| مقدار نزدیک صفر | دوره اندازهگیری تازه آغاز شده |
روش توصیهشده در Production ذخیره Snapshot و Delta است تا تاریخچه مانیتورینگ حفظ شود.
نکات فنی و تفسیر حرفهای
میانگین wait_time_ms بهازای درخواست، شدت معمول انتظار را نشان میدهد، اما توزیع را پنهان میکند. max_wait_time_ms برای دیدن رخداد پرت نیز مفید است.
نام Latch Class به پیادهسازی داخلی مربوط است و ممکن است تفسیر آن میان نسخهها تغییر کند. پیش از اقدام، مستندات رسمی و Known Issueهای Build جاری را بررسی کنید.
یک Latch پرانتظار میتواند پیامد فشار دیگری مانند Allocation Contention، کامپایل، رشد فایل یا ساختار خاص باشد. بررسی workload و Counterهای مکمل ضروری است.
Reset شمارندهها تاریخچه را پاک میکند؛ Snapshot و Delta در محیط Production ایمنتر و قابل ممیزیتر است.
بهینهسازی باید با تست بار و مقایسه قبل و بعد انجام شود. تغییر تنظیمات داخلی یا Trace Flag بدون شواهد میتواند مسئله جدیدی بسازد.
برای هر مشاهده، زمان UTC، نام سرور، نسخه، Uptime و شناسه رخداد را همراه خروجی ثبت کنید. این Metadata امکان تشخیص Restart، مقایسه درست Snapshotها و ممیزی تصمیمها را فراهم میکند.
همبستگی زمانی به معنی علت قطعی نیست. اگر Counter با کندی همزمان رشد کرد، فرضیهای بسازید که با Query، Plan، شاخص سیستمعامل یا آزمایش کنترلشده قابل رد یا تأیید باشد.
خطاهای رایج
- برابر دانستن Latch با Lock.
- قضاوت از مقدار تجمعی بدون Uptime.
- تمرکز فقط روی wait_time_ms و نادیده گرفتن تعداد و حداکثر.
- اعمال Trace Flag یا تغییر معماری بر اساس نام Latch Class تنها.
- Reset کردن Counterها بدون Snapshot و ثبت رخداد.
خطای مشترک دیگر، ارائه خروجی DMV بدون واحد، زمان Capture و توضیح دامنه Counter است. گزارش حرفهای باید به خواننده بگوید عدد دقیقاً چه چیزی را در چه بازهای اندازه گرفته است.
ملاحظات کارایی
Query مانیتورینگ را با ستونهای موردنیاز، فیلتر مشخص و TOP معقول بنویسید. دریافت همه ردیفها در فاصله بسیار کوتاه، بهویژه همراه متن SQL یا Plan، حجم داده و سربار پردازش مخزن را افزایش میدهد.
محاسبههای تاریخی و نمودارها را روی مخزن مانیتورینگ انجام دهید. سرور Production بهتر است فقط Snapshot خام و سبک را تولید کند. خطا، Timeout، Reset و Failover را بهعنوان وضعیت داده نگه دارید و با صفر ساختگی جایگزین نکنید.
بهترین روشها
- Delta را در بازه بار مسئلهدار اندازه بگیرید.
- کلاس Latch را با نسخه، Build و workload تطبیق دهید.
- میانگین، حداکثر، نرخ و مقدار کل را کنار هم گزارش کنید.
- تغییر را ابتدا در محیط آزمایش با بار مشابه بسنجید.
- نتیجه را با Wait Statistics، فایلها و Planها همبسته کنید.
پیش از تغییر، معیار موفقیت قابل اندازهگیری تعریف کنید و پس از تغییر همان بار و همان شاخصها را دوباره بسنجید. کاهش یک Counter داخلی زمانی ارزشمند است که Latency، Throughput یا پایداری سرویس نیز بهتر شود.
کاربرد واقعی در پروژه سازمانی
در سامانهای با چند سرویس، Snapshotهای sys.dm_os_latch_stats باید با شناسه سرور، برنامه، بازه Incident و رخدادهای Deploy در یک Timeline قرار گیرند. این کار امکان میدهد تیم DBA، توسعه و زیرساخت بهجای تبادل Screenshotهای پراکنده روی یک مجموعه داده مشترک گفتگو کنند.
در Runbook تعیین کنید چه کسی Collector را اجرا میکند، چه آستانهای Incident میسازد، چه دادهای حساس است و کدام اقدام نیازمند تأیید مدیر شیفت است. فرایند روشن معمولاً بیش از یک Query پیچیده زمان رفع مشکل را کاهش میدهد.
برای داشبورد، مقدار خام، Delta، نرخ بر ثانیه، Baseline و اثر کاربری را کنار هم نمایش دهید. رنگ هشدار باید از انحراف پایدار و چندشاخصی ساخته شود تا تیم با هشدارهای بیعمل خسته نشود.
سؤالات متداول
پرسش ۱: Latch در SQL Server چیست؟
قفل سبک داخلی برای حفاظت کوتاهمدت از ساختارهای حافظه و عملیات فیزیکی موتور است و با Lock تراکنشی تفاوت دارد.
پرسش ۲: sys.dm_os_latch_stats چه نوع دادهای میدهد؟
تعداد، زمان کل و بیشترین زمان انتظار را به تفکیک Latch Class از شروع Counterها ارائه میکند.
پرسش ۳: آیا Latch بالا به معنی نیاز قطعی به سختافزار است؟
خیر، ممکن است از الگوی دسترسی، رشد فایل، Allocation یا Build خاص ناشی شود. تحلیل تخصصی پیش از خرید زیرساخت از هزینه اشتباه جلوگیری میکند.
پرسش ۴: چگونه اثر تجاری Latch Contention سنجیده میشود؟
Delta زمان Latch باید با Latency تراکنش، Throughput و SLA در همان بازه همبسته شود تا اثر واقعی بر کاربر مشخص گردد.
پرسش ۵: فرق Latch و Lock چیست؟
Lock سازگاری منطقی تراکنش را کنترل میکند؛ Latch ساختار داخلی یا فیزیکی را برای مدت کوتاه محافظت میکند.
پرسش ۶: چه زمانی مشاوره SQL Internals لازم است؟
وقتی یک Latch Class پایدار و شدید است و ارتباط آن با workload روشن نیست، بررسی Build، Dumpهای تشخیصی و تست بار تخصصی ارزشمند است.
پرسش ۷: رایجترین اشتباه درباره latch_class چیست؟
تبدیل مستقیم نام کلاس به یک نسخه درمانی ثابت است. نام فقط مسیر بررسی را نشان میدهد و Context نسخه و بار ضروری است.
پرسش ۸: جمعآوری Latch Stats چه سرباری دارد؟
خواندن ستونهای محدود سبک است؛ سربار اصلی از Polling پرتکرار، ذخیره بیحد و Joinهای غیرضروری در سامانه مانیتورینگ میآید.
پرسش ۹: بهترین روش اندازهگیری Latch چیست؟
دو Snapshot معتبر با Uptime ثابت بگیرید، Delta و نرخ را محاسبه و با Baseline و شاخص کاربری مقایسه کنید.
پرسش ۱۰: آیا کلاسها در همه نسخهها یکساناند؟
خیر، جزئیات داخلی و مجوزها میتوانند تغییر کنند. مستندات و Build دقیق SQL Server مقصد را کنترل کنید.
سؤالات مصاحبهای
دامنه داده sys.dm_os_latch_stats چیست؟
Counterهای تجمعی را بر اساس کلید اصلی DMV ارائه میکند و برای بازه باید Delta محاسبه شود.
چرا Snapshot زماندار ضروری است؟
بدون زمان Capture نمیتوان نرخ، Delta، همبستگی با Incident یا اعتبار بازه پس از Restart را تعیین کرد.
چگونه تقسیم بر صفر را در نرخها مدیریت میکنید؟
در مخرج از NULLIF استفاده میکنیم و NULL را بهعنوان داده غیرقابل محاسبه نگه میداریم، نه اینکه همیشه آن را صفر فرض کنیم.
چه زمانی مقدار تجمعی گمراهکننده است؟
وقتی Uptime طولانی، workload تغییرکرده یا Counter در میانه مقایسه Reset شده باشد. Delta بازه همنوع راهحل اصلی است.
چگونه سربار Collector را کنترل میکنید؟
ستون و ردیف محدود، Interval هدفمند، جداسازی Snapshot خام از تحلیل و Retention چندلایه استفاده میشود.
چرا Correlation برای اثبات علت کافی نیست؟
دو متریک ممکن است از علت سوم اثر بگیرند. Query، Plan یا آزمایش کنترلشده برای کامل کردن زنجیره علت لازم است.
چکلیست نهایی
- مجوز و دامنه دید کنترل شده است.
- زمان UTC و Uptime ثبت شده است.
- واحد و دامنه Counter مشخص است.
- Snapshot با Baseline مناسب مقایسه شده است.
- NULL، Restart و Reset مدیریت شدهاند.
- شواهد مکمل برای فرضیه جمع شدهاند.
- معیار موفقیت تغییر و روش بازگشت تعریف شده است.
جمعبندی
sys.dm_os_latch_stats وقتی بیشترین ارزش را دارد که در یک فرایند منظم اندازهگیری، تفسیر و آزمون استفاده شود. مثالهای این مقاله الگوی Query ایمن را نشان میدهند، اما آستانه و اقدام باید از Baseline و معماری واقعی شما استخراج شود.
برای دیدن ارتباط این DMV با چهار ابزار دیگر، به مقاله مادر Wait Statistics در SQL Server بازگردید.