SQLSERVER獨特的任務調度演算法”SQLOS”

來源:互聯網
上載者:User
 SQLSERVER獨特的任務調度演算法"SQLOS"

微軟開發SQLOS的背景:

SQLSERVER作為一個企業級資料庫平台,一個基本的要求就是要有能力順暢地同時處理成百上千的使用者請求,SQLSERVER要使線程調度

得更加適應高並發的資料庫應用。

由於以上背景:
SQLSERVER在Windows的基礎上開發出了一套自己的任務調度機制。所以SQLSERVER作為一個應用程式,又抽象出一般由作業系統代為

管理的功能,例如:
任務調度管理子系統
記憶體管理
錯誤,異常處理機制
死結偵測和解決機制
運行第三方代碼(dll,extended SP等)機制

 

SQLSERVER的管理功能組件又叫SQLOS SQL OPERATING SYSTEM ,而記憶體管理和任務調度管理是SQLOS的兩大核心內容

對於SQLSERVER來講,除了從DAC dedicated administrator connection過來的串連,其他使用者串連對SQL來講都是同等重要的,

而這樣的串連在同一個時間點,可能會有成百上千。 所以SQLSERVER完全依賴Windows任務調度是不行的。

 

SQLSERVER的這一套任務調度機制的特點:

1、只有需要運行任務的串連才會被分配線程。出於空閑狀態的串連,在SQLSERVER裡會以一組資料結構表示,所以不會佔用線程資源。大大降低

SQLSERVER進程需要的線程數目

2、對於每一個CPU,SQLSERVER內部會有一個調度(scheduler),由這個scheduler決定在某個時間點,到底是哪個SQLSERVER線程去運行。

所以在Windows層面,每個CPU最多隻會對應一個處於運行狀態的線程。大大降低Windows層面的環境切換context switch

實踐證明:很多有著1000~2000個並發使用者的SQLSERVER,線程數也只需要一兩百個。SQLSERVER完成的批處理量每秒鐘可以達到3000~4000個。

 

SQLOS的幾個概念:

 scheduler

對於每個邏輯CPU,SQLSERVER會有一個scheduler與之對應,在SQL層面上代表CPU對象,只有拿到scheduler所有權的任務worker才能在這個邏輯CPU上運行

所謂邏輯CPU,就是SQLSERVER從Windows層面上看到的CPU數目,如果是一個雙核的CPU,那麼一個物理CPU在SQL看來就是兩個邏輯CPU。如果系統還使用了

超執行緒hyper-threaded ,那對SQLSERVER來講就是4個邏輯CPU

規則: 每個scheduler上的最大worker數目等於SQLSERVER的最大線程數除以scheduler的數目 ,在同一個時間點,只能有一個擁有scheduler的worker處於運行

狀態,其他worker都必須處於等待狀態。這樣能降低每個邏輯CPU上的處於執行狀態的線程數目,降低context switch,提供可擴充性

scheduler是SQLSERVER的一個邏輯概念,他不與物理CPU相綁定。也就是說,一個scheduler可以被Windows安排一會兒在這個CPU上,一會兒在那個CPU上。

但是,如果在sp_configure裡設定了CPU affinity mask,那麼scheduler就會固定在某個特定的CPU上

 

worker

每個worker跟一個線程(或纖程fiber)相對應,是SQLSERVER任務的執行單位。SQLSERVER不直接調度線程/纖程,而是調度worker,使得SQLSERVER能夠控制

任務調度

規則: 每個worker會固定代表一個線程(或纖程),並且和一個scheduler相綁定。如果scheduler是固定在某個CPU上的(通過設定CPU affinity mask),那麼

worker也會固定在某個CPU上

每個scheduler有worker的上限值,並且可以根據SQLSERVER工作負載建立或釋放worker,每次worker都會去運行一個完整的任務(task)。在任務做完之前不會

退出,除非這個任務主動進入等待狀態。

scheduler只在有新任務要運行,而當前沒有閒置worker的情況下,才會建立新的worker。

某個worker空閑超過15分鐘,scheduler可能會刪除這個worker,以及其對應的線程。當SQLSERVER遇到記憶體壓力的時,也會大量刪除處於空閑狀態的worker,以

節省multi-page的記憶體開銷

各種CPU和SQLSERVER版本組合自動設定的最大背景工作執行緒數
CPU數                 32位電腦                        64位電腦
<=4                     256                                  512
8                          288                                  576
16                        352                                  704
32                        480                                  960

 

task

在worker上啟動並執行最小任務單元。最簡單的task就是一個簡單batch。例如,客戶發過來下面的請求:

1 SELECT @@SERVERNAME 2 GO3 SELECT GETDATE() 4 GO 

那麼這兩個batch就分別是兩個task。SQLSERVER會先分配給第一個batch(select @@servername)一個worker,將結果返回給用戶端,再分配第二個batch

(select getdate())一個worker。這兩個worker可能是不同的worker,甚至在不同的scheduler上

只要一個task開始運行,他就不會從這個worker上被移出。例如,如果一個select語句被其他串連阻塞住,worker就不能繼續運行,只能進入等待狀態。但是這個

select task 不會將這個worker釋放,讓他做其他任務。所以結果是這個worker所對應的線程會進入等待狀態

 

yieding

 SQLOS的任務調度演算法的核心,就是所有在邏輯scheduler上啟動並執行worker都是非搶佔式的 (non-preemptive)。worker始終在scheduler上運行,直到他運行結束,或者主動將scheduler讓出給其他worker為止。這個“讓出”scheduler的動作,我們叫yieding

每個scheduler都會有一個runnable列表,所有等待CPU啟動並執行worker都會在這個列表裡排隊,以先進先出的演算法,等待SQL分配給他scheduler運行

SQLSERVER定義了很多yieding的規則,約束一個task在scheduler啟動並執行時間。如果task比較複雜,不能很快完成,會保證task在合適的時間點做yieding,不至於佔用scheduler太多時間。

常見時間點:

1、當worker每次要去讀資料頁的時候,SQLSERVER會檢查這個worker已經在scheduler上運行了多久,如果已經超過4ms,就做yieding

2、每做64KB的結果集排序,就會做一次yieding

3、在做語句編譯compile的過程中(這個過程比較占CPU資源),經常會有yieding

4、如果用戶端不能及時把結果集取走,worker就會做yieding

5、一個batch裡的每一句話做完,都會做一次yieding

正常來講,哪怕一個task要做很久,他使用的worker是會經常做yieding的,不會長時間佔用CPU不放。如果在一個scheduler上同時有很多worker要運行,

SQLSERVER通過worker自動yieding的方式調度並發運行。這個比Windows用環境切換context switch更有效

 

 下面用圖來說明SQLOS的任務調度演算法:

 

總結:

對於每個CPU,SQLSERVER都會有一個scheduler與之對應。在每個scheduler裡,會有若干個worker,對應
於每個線程。在用戶端發過來請求之後,SQL會將其分解成一個或多個task。根據每個scheduler的繁忙程度,
task會被分配到某個scheduler上。如果scheduler裡有閒置worker,task就會被分配到某個worker上。
如果沒有,scheduler會建立新的worker,供task使用。如果scheduler裡的worker已經到了他的上限值,
而他們都有task要運行,那麼新的task只好進入等待worker的狀態

使用下面兩個SQL語句可以查看當前SQLSERVER有多少個workers在工作,有多少個tasks在運行

1 SELECT * FROM sys.dm_os_workers2 SELECT * FROM  sys.dm_os_tasks

----------------------------------------------------------華麗的分割線---------------------------------------------------------

說一下上面的圖的含義

SELECT * FROM sys.dm_os_workers

其他列的解釋大家可以看一下MSDN

http://msdn.microsoft.com/zh-cn/library/ms178626(v=SQL.105).aspx

------------------------------------------------------------------------------------------------------------

SELECT * FROM  sys.dm_os_tasks

任務的狀態可以是下列選項之一

PENDING:正在等待背景工作執行緒。

RUNNABLE:可運行,但正在等待接收配量。

RUNNING:當前正在排程器中運行。

SUSPENDED:具有背景工作執行緒,但正在等待事件。

DONE:已完成。

SPINLOOP:陷入自旋鎖

MSDN的解釋:http://msdn.microsoft.com/zh-cn/library/ms174963(v=SQL.105).aspx

久沒有寫文章了,希望大家看了我的文章能夠更加深入瞭解SQLSERVER

要睡了,熬不住了~

2013-6-3

附草圖一張

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.