1. 程式人生 > >sql server 性能調優 資源等待之PAGEIOLATCH_x

sql server 性能調優 資源等待之PAGEIOLATCH_x

sig 子線程 調度 分享 頁面 緩存 windows cpu 想要

一.概念

  在介紹資源等待PAGEIOLATCH_x之前,先來了解下從實例級別來分析的各種資源等待的dmv視圖sys.dm_os_wait_stats。它是返回執行的線程所遇到的所有等待的相關信息,該視圖是從一個實際級別來分析的各種等待,它包括200多種類型的等待,主要關註的包括了PageIoLatch磁盤I/O讀寫的等待時間,LCK_xx鎖的等待時間,日誌WriteLog寫入等待,頁上閂鎖PageLatch等待以及其它。

  1. 下面根據總耗時排序來觀察,這裏分析的等待的wait_type 不包括以下

SELECT  wait_type ,
        waiting_tasks_count,
        signal_wait_time_ms ,
        wait_time_ms,
        max_wait_time_ms
FROM sys.dm_os_wait_stats WHERE wait_time_ms > 0 AND wait_type NOT IN ( CLR_SEMAPHORE, CLR_AUTO_EVENT, LAZYWRITER_SLEEP, RESOURCE_QUEUE, SLEEP_TASK, SLEEP_SYSTEMTASK, SQLTRACE_BUFFER_FLUSH
, WAITFOR, LOGMGR_QUEUE, CHECKPOINT_QUEUE, REQUEST_FOR_DEADLOCK_SEARCH, XE_TIMER_EVENT, BROKER_TO_FLUSH, BROKER_TASK_STOP, CLR_MANUAL_EVENT,
DISPATCHER_QUEUE_SEMAPHORE, FT_IFTS_SCHEDULER_IDLE_WAIT, XE_DISPATCHER_WAIT, XE_DISPATCHER_JOIN, SQLTRACE_INCREMENTAL_FLUSH_SLEEP ) ORDER BY signal_wait_time_ms DESC

  通過上面的查詢就能找到PAGEIOLATCH_x類型的資源等待,由於是實例級別的統計,想要獲得有意義數據,就需要查看感興趣的時間間隔。如果要間隔來分析,不需要重啟服務,可通過以下命令來重置

DBCC SQLPERF (sys.dm_os_wait_stats, CLEAR);  

  wait_type:等待類型
  waiting_tasks_count:該等待類型的等待數
  wait_time_ms:該等待類型的總等待時間(包括一個進程懸掛狀態(Suspend)和可運行狀態(Runnable)花費的總時間)
  max_wait_time_ms:該等待類型的最長等待時間
  signal_wait_time_ms:正在等待的線程從收到信號通知到其開始運行之間的時差(一個進程可運行狀態(Runnable)花費的總時間)
  io等待時間==wait_time_ms - signal_wait_time_ms

二. PAGEIOLATCH_x

  2.1 什麽是Latch

    在sql server裏latch是輕量級鎖,不同於lock。latch是用來同步sqlserver的內部對象(同步資源訪問),而lock是用來對於用戶對象包括(表,行,索引等)進行同步,簡單概括:Latch用來保護SQL server內部的一些資源(如page)的物理訪問,可以認為是一個同步對象。而lock則強調邏輯訪問。比如一個table,就是個邏輯上的概念。關於lock鎖這塊在"sql server 鎖與事務撥雲見日"中有詳細說明。

  2.2 什麽是PageIOLatch 

  用來同步訪問數據庫PAGE的latch就是PAGELATCH了。SQL server的Buffpool裏每個數據庫頁(8kb的PAGE)都有一個對應的LATCH。 要訪問某個PAGE必須首先獲得這個PAGE的LATCH。
  當查詢的數據頁如果在Buffer pool裏找到了,則沒有任何等待。否則就會發出一個異步io操作,將頁面讀入到buffer pool,沒做完之前,連接會保持在PageIoLatch_ex(寫)或PageIoLatch_sh(讀)的等待狀態,是Buffer pool與磁盤之間的等待。它反映了查詢磁盤i/o讀寫的等待時間。
  當sql server將數據頁面從數據文件裏讀入內存時,為了防止其他用戶對內存裏的同一個數據頁面進行訪問,sql server會在內存的數據頁同上加一個排它鎖latch,而當任務要讀取緩存在內存裏的頁面時,會申請一個共享鎖,像是lock一樣,latch也會出現阻塞,根據不同的等待資源,等待狀態有如下:PAGEIOLATCH_DT,PAGEIOLATCH_EX,PAGEIOLATCH_KP,PAGEIOLATCH_SH,PAGEIOLATCH_UP。重點關註PAGEIOLATCH_EX(寫入)和PAGEIOLATCH_SH(讀取)二種等待

2.1 AGEIOLATCH流程圖

  有時我們分析當前活動用戶狀態下時,一個有趣的現象是,有時候你發現某個SPID被自己阻塞住了,等待的latch是PAGEIOLATCH_SH. 為什麽會自己等待自己呢? 這個得從SQL server讀取頁的過程說起。SQL server從磁盤讀取一個page的過程如下:

技術分享圖片

  (1):由一個用戶請求,獲取掃描X表,由Worker x去執行。

  (2):在掃描過程中找到了它需要的數據頁同1:100。

  (3):發面頁面1:100並不在內存中的數據緩存裏。

  (4):sql server在緩沖池裏找到一個可以存放的頁面空間,在上面加EX的LATCH鎖,防止數據從磁盤裏讀出來之前,別人也來讀取或修改這個頁面。

  (5):worker x發起一個異步i/o請求,要求從數據文件裏讀出頁面1:100。

  (6):由於是異步i/o(可以理解為一個task子線程),worker x可以接著做它下面要做的事情,就是讀出內存中的頁面1:100,讀取的動作需要申請一個sh的latch。

  (7):由於worker x之前申請了一個EX的LATCH鎖還沒有釋放,所以這個sh的latch將被阻塞住,worker x被自己阻塞住了,等待的資源就是PAGEIOLATCH_SH。

  最後當異步i/o結束後,系統會通知worker x,你要的數據已經寫入內存了。接著EX的LATCH鎖釋放,worker x申請得到了sh的latch鎖。

總結:首先說worker是一個執行單元,下面有多個task來關聯是在Worker上運行的最小任務單元,可以是這麽理解worker產生了第一個x的task任務,再第5步發起一個異步i/o請求是第二個task任務。二個task屬於一個worker,worker x被自己阻塞住了。 關於任務調度了解查看sql server 任務調度與CPU。

2.2 具體分析

  通過上面了解到如果磁盤的速度不能滿足sql server的需要,它就會成為一個瓶頸,通常PAGEIOLATCH_SH 從磁盤讀數據到內存,如果內存不夠大,有內存壓力時它會釋放掉,數據頁就不會在內存的數據緩存裏,這樣內存問題就導致了磁盤的瓶頸。PAGEIOLATCH_EX是寫入數據,這一般是磁盤的寫入速度明顯跟不上,與內存沒有直接關系。

下面是查詢PAGEIOLATCH_x的資源等待時間:

select wait_type,
waiting_tasks_count,
wait_time_ms ,
max_wait_time_ms,
signal_wait_time_ms
from sys.dm_os_wait_stats
where wait_type like PAGEIOLATCH% 
order by wait_type

通過上面的sql 查詢,可以定期清空數據做統計的數據分析,當發現有異常時,要結全業務來分析內存與磁盤。關於內存查看”sql server 內存初探“磁盤查看"sql server I/O硬盤交互" 後面後從windows系統性能監視器方面來分析。

  

  

sql server 性能調優 資源等待之PAGEIOLATCH_x