sql server 性能調優 資源等待之PAGEIOLATCH_x
一.概念
在介紹資源等待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_msFROM 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