مثالهای عملی و قابل اجرا
مثال 1: خواندن شمارنده تجمعی PAGELATCH_UP
اولین گام این است که وجود و اندازه تاریخی PAGELATCH_UP را ببینید. ستون wait_time_ms شامل signal_wait_time_ms نیز هست و مقدار از زمان Startup یا آخرین پاکسازی Wait Stats تجمع یافته است.
SELECT
wait_type,
waiting_tasks_count,
wait_time_ms,
signal_wait_time_ms,
CAST(wait_time_ms * 1.0 /
NULLIF(waiting_tasks_count, 0) AS decimal(18,2)) AS avg_wait_ms
FROM sys.dm_os_wait_stats
WHERE wait_type = N'PAGELATCH_UP';
| Wait Type | تعداد | زمان کل | میانگین |
|---|
| PAGELATCH_UP | 12,480 | 3,842,000 ms | 307.85 ms |
این خروجی Baseline است و رخداد جاری را اثبات نمیکند. زمان Startup، workload و Delta بعدی را ثبت کنید تا درباره اهمیت PAGELATCH_UP نتیجهگیری شود.
مثال 2: محاسبه Delta پنجثانیهای PAGELATCH_UP
دو Snapshot کوتاه نشان میدهد در بازه مشاهده چه مقدار انتظار جدید ساخته شده است. برای محیط واقعی، بازه را با چرخه کاری سامانه هماهنگ کنید و Snapshotها را در جدول مانیتورینگ پایدار نگه دارید.
IF OBJECT_ID(N'tempdb..#WaitStart') IS NOT NULL
DROP TABLE #WaitStart;
SELECT wait_type, waiting_tasks_count, wait_time_ms, signal_wait_time_ms
INTO #WaitStart
FROM sys.dm_os_wait_stats
WHERE wait_type = N'PAGELATCH_UP';
WAITFOR DELAY '00:00:05';
SELECT
w.wait_type,
w.waiting_tasks_count - ISNULL(b.waiting_tasks_count, 0) AS delta_tasks,
w.wait_time_ms - ISNULL(b.wait_time_ms, 0) AS delta_wait_ms,
w.signal_wait_time_ms - ISNULL(b.signal_wait_time_ms, 0) AS delta_signal_ms
FROM sys.dm_os_wait_stats AS w
LEFT JOIN #WaitStart AS b ON b.wait_type = w.wait_type
WHERE w.wait_type = N'PAGELATCH_UP';
| Wait Type | Delta Task | Delta Wait | Delta Signal |
|---|
| PAGELATCH_UP | 38 | 8,420 ms | 310 ms |
Delta را به نرخ بر ثانیه و تعداد تراکنش نرمال کنید. یک پنجره پنجثانیهای برای آموزش است و در سامانه کمترافیک ممکن است نماینده نباشد.
مثال 3: یافتن Requestهای فعال روی PAGELATCH_UP
وقتی PAGELATCH_UP در لحظه رخ میدهد، Session، وضعیت، منبع انتظار و Blocker را یکجا ثبت کنید. این Snapshot به اتصال آمار Instance-level به رخداد واقعی کمک میکند.
SELECT
r.session_id,
DB_NAME(r.database_id) AS database_name,
r.status,
r.command,
r.wait_time,
r.wait_resource,
r.blocking_session_id,
r.cpu_time,
r.total_elapsed_time
FROM sys.dm_exec_requests AS r
WHERE r.wait_type = N'PAGELATCH_UP'
ORDER BY r.wait_time DESC;
| Session | پایگاه داده | منبع | زمان |
|---|
| 74 | a00b | PAGELATCH_UP resource | 4,280 ms |
اگر خروجی خالی است، انتظار در همان لحظه فعال نیست؛ این موضوع با بالا بودن مقدار تجمعی تناقض ندارد و اهمیت Capture دورهای را نشان میدهد.
مثال 4: بررسی Taskها و Contextهای منتظر PAGELATCH_UP
یک Request میتواند چند Task داشته باشد، بهویژه در Plan موازی. sys.dm_os_waiting_tasks جزئیات worker و resource_description را برای تحلیل سطح پایینتر فراهم میکند.
SELECT
wt.session_id,
wt.exec_context_id,
wt.wait_duration_ms,
wt.wait_type,
wt.blocking_session_id,
wt.resource_description
FROM sys.dm_os_waiting_tasks AS wt
WHERE wt.wait_type = N'PAGELATCH_UP'
ORDER BY wt.wait_duration_ms DESC;
| Session | Context | مدت | Resource |
|---|
| 74 | 0 | 4,280 ms | resource details |
تعداد Taskها را با DOP، Blocking و ماهیت Latch حافظه و تخصیص تفسیر کنید؛ یک Task منفرد و کوتاه با صف گسترده و پایدار یکسان نیست.
مثال 5: نمایش متن SQL عامل PAGELATCH_UP
برای رسیدن از Wait به اقدام اصلاحی باید متن Batch و Statement جاری را ثبت کرد. Offsetها باعث میشوند بخش در حال اجرای Batch جدا از متن کامل نمایش داده شود.
SELECT
r.session_id,
r.wait_time,
r.wait_resource,
SUBSTRING(st.text,
(r.statement_start_offset / 2) + 1,
((CASE r.statement_end_offset
WHEN -1 THEN DATALENGTH(st.text)
ELSE r.statement_end_offset
END - r.statement_start_offset) / 2) + 1) AS current_statement,
st.text AS batch_text
FROM sys.dm_exec_requests AS r
OUTER APPLY sys.dm_exec_sql_text(r.sql_handle) AS st
WHERE r.wait_type = N'PAGELATCH_UP'
ORDER BY r.wait_time DESC;
| Session | Wait | Statement | Batch |
|---|
| 74 | 4,280 ms | SELECT/UPDATE جاری | نام Procedure یا Batch |
متن Query ممکن است اطلاعات حساس داشته باشد؛ آن را در مخزن مانیتورینگ امن نگه دارید و برای اصلاح PAGELATCH_UP حتماً Execution Plan و پارامترها را نیز جمعآوری کنید.
مثال 6: یافتن ایندکس دارای Page Latch برای PAGELATCH_UP
index_operational_stats شمارندههای Latch را در سطح ایندکس ارائه میکند. این گزارش Object و Indexهایی را که بیشترین زمان Page Latch دارند برجسته میکند.
SELECT TOP (20)
DB_NAME(ios.database_id) AS database_name,
OBJECT_SCHEMA_NAME(ios.object_id, ios.database_id) AS schema_name,
OBJECT_NAME(ios.object_id, ios.database_id) AS object_name,
i.name AS index_name,
ios.page_latch_wait_count,
ios.page_latch_wait_in_ms
FROM sys.dm_db_index_operational_stats(NULL, NULL, NULL, NULL) AS ios
LEFT JOIN sys.indexes AS i
ON i.object_id = ios.object_id
AND i.index_id = ios.index_id
WHERE ios.page_latch_wait_count > 0
ORDER BY ios.page_latch_wait_in_ms DESC;
| پایگاه داده | شیء | ایندکس | Latch ms |
|---|
| a00b | dbo.OrderQueue | PK_OrderQueue | 184200 |
اگر یک ایندکس ترتیبی در PAGELATCH_EX غالب باشد، Last-page insert را بررسی کنید؛ برای PAGELATCH_UP صفحات تخصیص tempdb نیز محتملاند.
مثال 7: بازبینی تعداد و اندازه فایلهای tempdb
رقابت تخصیص tempdb یکی از سناریوهای PAGELATCH_UP است. فایلها باید اندازه و Growth متناسب داشته باشند تا تخصیص بهصورت متوازنتری انجام شود.
SELECT
file_id,
name,
physical_name,
CAST(size / 128.0 AS decimal(18,2)) AS size_mb,
CASE WHEN is_percent_growth = 1
THEN CONCAT(growth, N'%')
ELSE CONCAT(CAST(growth / 128.0 AS decimal(18,2)), N' MB')
END AS growth_setting
FROM tempdb.sys.database_files
ORDER BY file_id;
| File ID | نام | اندازه | Growth |
|---|
| 1 | tempdev | 8192 MB | 1024 MB |
| 3 | temp2 | 8192 MB | 1024 MB |
افزودن فایل بیش از نیاز نیز هزینه مدیریت دارد؛ تعداد هسته، نسخه SQL Server و شواهد واقعی Contention را مبنا قرار دهید.
مثال 8: استخراج wait_resource برای صفحه داغ PAGELATCH_UP
wait_resource و resource_description فایل و صفحه مورد رقابت را نشان میدهند. تکرار یک شناسه صفحه در Sessionهای متعدد، سرنخ مهمی برای Hot Page است.
SELECT
r.session_id,
r.wait_type,
r.wait_time,
r.wait_resource,
wt.resource_description,
DB_NAME(r.database_id) AS database_name
FROM sys.dm_exec_requests AS r
LEFT JOIN sys.dm_os_waiting_tasks AS wt
ON wt.session_id = r.session_id
AND wt.exec_context_id = r.request_id
WHERE r.wait_type = N'PAGELATCH_UP'
ORDER BY r.wait_time DESC;
| Session | Wait Resource | توضیح | زمان |
|---|
| 76 | 2:1:124 | dbid=2 fileid=1 pageid=124 | 9200 ms |
برای صفحههای سیستم tempdb، نوع PFS/GAM/SGAM را بررسی کنید؛ برای صفحه ایندکس، Object و الگوی Insert را بیابید.
مثال 9: مقایسه PAGELATCH_UP با Waitهای همخانواده
Wait Typeها در خلأ تفسیر نمیشوند. مقایسه PAGELATCH_UP با PAGELATCH_EX، PAGEIOLATCH_EX، LATCH_EX کمک میکند بفهمید علامت اصلی به کدام زیرسیستم نزدیکتر است.
SELECT
wait_type,
waiting_tasks_count,
wait_time_ms,
signal_wait_time_ms,
CAST(100.0 * wait_time_ms /
NULLIF(SUM(wait_time_ms) OVER (), 0) AS decimal(10,2)) AS family_percent
FROM sys.dm_os_wait_stats
WHERE wait_type IN (N'PAGELATCH_UP', N'PAGELATCH_EX', N'PAGEIOLATCH_EX', N'LATCH_EX')
ORDER BY wait_time_ms DESC;
| Wait Type | تعداد | زمان | سهم خانواده |
|---|
| PAGELATCH_UP | 12,480 | 3,842,000 ms | 64.20% |
| PAGELATCH_EX | 4,110 | 1,820,000 ms | 30.42% |
سهم خانواده برای Prioritization مفید است، ولی شدت کسبوکاری را نشان نمیدهد. زمان پاسخ، SLA و تعداد درخواست متاثر را هم اضافه کنید.
مثال 10: ساخت قاعده هشدار مستقل برای Delta PAGELATCH_UP
در مانیتورینگ بهتر است روی Delta یک بازه ثابت و نرخ هر ثانیه هشدار بسازید، نه روی مقدار تجمعی از Startup. مثال مستقل زیر با داده نمونه منطق سطحبندی را نمایش میدهد و در سامانه مانیتورینگ با Snapshot واقعی جایگزین میشود.
DECLARE @WindowSeconds int = 60;
DECLARE @WaitDelta TABLE
(
wait_type nvarchar(60),
delta_wait_ms bigint,
delta_tasks bigint
);
INSERT INTO @WaitDelta (wait_type, delta_wait_ms, delta_tasks)
VALUES (N'PAGELATCH_UP', 8400, 38);
SELECT
wait_type,
delta_wait_ms,
delta_tasks,
CAST(delta_wait_ms * 1.0 / @WindowSeconds AS decimal(18,2)) AS wait_ms_per_second,
CASE
WHEN delta_wait_ms >= 30000 THEN N'بحرانی'
WHEN delta_wait_ms >= 5000 THEN N'نیازمند بررسی'
ELSE N'عادی'
END AS alert_level
FROM @WaitDelta;
| Wait Type | Delta | نرخ | سطح |
|---|
| PAGELATCH_UP | 8,400 ms | 140 ms/s | نیازمند بررسی |
آستانههای نمونه عمومی نیستند. آنها را از Baseline، ظرفیت و SLA سامانه خود استخراج کنید تا برای PAGELATCH_UP هشدار کاذب تولید نشود.
سؤالات متداول
سؤال 1: PAGELATCH_UP دقیقاً چه زمانی در SQL Server ثبت میشود؟
PAGELATCH_UP انتظار گرفتن Update Latch روی بافری است که درخواست I/O فعال ندارد. این انتظار اغلب در صفحههای تخصیص PFS، GAM و SGAM بهویژه در tempdb یا در صفحههای داغ دیده میشود. ثبت یک انتظار کوتاه بخشی طبیعی از زمانبندی موتور است؛ اهمیت زمانی ایجاد میشود که Delta آن با کندی قابل مشاهده و افت SLA همزمان باشد.
سؤال 2: برای شروع تحلیل PAGELATCH_UP کدام DMVها مناسباند؟
sys.dm_os_wait_stats برای روند Instance، sys.dm_exec_requests برای Request جاری و sys.dm_os_waiting_tasks برای Task و منبع انتظار نقطه شروع هستند. با توجه به دسته Latch حافظه و تخصیص باید DMV تخصصی همان زیرسیستم و Execution Plan نیز افزوده شود.
سؤال 3: آیا زیاد بودن PAGELATCH_UP به معنی نیاز فوری به سختافزار جدید است؟
خیر. این انتظار مشکل کندی دیسک نیست؛ افزودن Storage سریعتر بدون رفع Contention حافظه معمولاً مؤثر نیست. پیش از خرید باید هزینه اصلاح Query، تنظیمات، معماری برنامه و زیرساخت با اندازهگیری قبل و بعد مقایسه شود؛ یک ارزیابی فنی حرفهای میتواند از هزینه اشتباه جلوگیری کند.
سؤال 4: چه زمانی تحلیل حرفهای PAGELATCH_UP برای یک کسبوکار توجیه دارد؟
وقتی انتظار با افت فروش، Timeout، ناتمام ماندن Job، افزایش زمان پاسخ یا نقض SLA همبسته است، تحلیل ساختاریافته ارزش تجاری دارد. مشاوره SQL Server در این مرحله باید خروجی قابل سنجش مانند کاهش p95 و نرخ انتظار ارائه کند، نه فقط تغییر چند تنظیم.
سؤال 5: تفاوت PAGELATCH_UP با PAGELATCH_EX چیست؟
PAGELATCH_UP در دسته Latch حافظه و تخصیص تفسیر میشود، در حالی که PAGELATCH_EX مرحله یا منبع متفاوتی را برجسته میکند. همزمانی این دو ممکن است زنجیره علت و معلول باشد؛ تعریف هر Wait، منبع جاری و Timeline تعیین میکند کدامیک علامت و کدامیک علت نزدیکتر است.
سؤال 6: برای سفارش پروژه کاهش PAGELATCH_UP چه دادههایی باید آماده شود؟
بازه دقیق کندی، نسخه و Edition، Wait Delta، Query و Plan، شاخصهای سیستمعامل، توپولوژی و SLA را آماده کنید. حذف اطلاعات حساس و فراهم کردن نمونه قابل بازتولید باعث میشود خدمت عیبیابی سریعتر، کمریسکتر و قابل ارزیابی باشد.
سؤال 7: رایجترین خطای تشخیصی درباره PAGELATCH_UP چیست؟
قضاوت با مقدار تجمعی از زمان Startup و تغییر تنظیمات بدون اتصال انتظار به Query و بازه حادثه رایجترین خطاست. این انتظار مشکل کندی دیسک نیست؛ افزودن Storage سریعتر بدون رفع Contention حافظه معمولاً مؤثر نیست. Snapshot کوتاه، Baseline و مقایسه قبل و بعد این خطا را کاهش میدهد.
سؤال 8: اثر PAGELATCH_UP بر Performance چگونه اندازهگیری میشود؟
Delta wait_time_ms، تعداد Task، متوسط انتظار و نرخ بر ثانیه را کنار throughput، p95 زمان پاسخ و منابع سیستم ثبت کنید. کندی workloadهای موقت، افت مقیاسپذیری و صف شدن workerها روی یک صفحه داخلی بنابراین معیار فنی باید به معیار تجربه کاربر یا Job کسبوکار متصل شود.
سؤال 9: Best Practice اصلی برای مدیریت PAGELATCH_UP چیست؟
wait_resource را به فایل و صفحه نگاشت و توزیع فایلهای tempdb و الگوی اشیای موقت را بررسی کنید. تغییر را ابتدا در محیط آزمایش یا روی دامنه محدود اعمال کنید، معیار موفقیت را از قبل بنویسید و امکان بازگشت داشته باشید. پاک کردن Wait Stats بدون ذخیره Baseline یا اجرای چند تغییر همزمان قابلیت استناد نتیجه را از بین میبرد.
سؤال 10: PAGELATCH_UP با کدام نسخههای SQL Server سازگار است؟
نسخههای متداول SQL Server؛ برخی بهبودهای tempdb در نسخههای جدید خودکار شدهاند. ستونها و Permissionهای DMV ممکن است میان نسخههای On-premises، Azure SQL و نسخههای جدید تغییر کنند؛ Query تشخیصی را در مستندات همان نسخه کنترل و ابتدا با دسترسی Read-only مناسب اجرا کنید.