文章出處

在 SQL Server 中,當數據庫啟動后,SQL Server 會為每個物理 CPU(包括 Physical CPU 和 Hyperthreaded)創建一個對應的任務調度器(Scheduler),Scheduler 可以看作為邏輯 CPU(Logical CPU)。

根據 Affinity Mask 選項的配置,Scheduler 的狀態被設置為 ONLINE 或 OFFLINE。使用下面的 SQL 來查詢當前環境中 Scheduler 的狀態。

SELECT is_online
    ,[status]
    ,COUNT(*) AS [count]
FROM sys.dm_os_schedulers
WHERE scheduler_id < 255
GROUP BY is_online
    ,[status];

默認的 Affinity Mask 是 0,也就是所有 Scheduler 均為 ONLINE。

SELECT *
FROM sys.configurations
WHERE [name] LIKE '%affinity%';

例如,如果把 Affinity Mask 設置為 3,即 00000011,則意味著只有 0 和 1 號 CPU 可以使用。

假設有 64 個 CPU,則常用的 Affinity Mask 值有:

  • 255 -> 0xFF
  • 65280 -> 0xFF00
  • 16711680 -> 0xFF0000
  • 4278190080 -> 0xFF000000
  • 4294967040 -> 0xFFFFFF00
  • -256 -> 0xFFFFFF00

下面的 VM 的配置為 4 * 8 = 32 Logical CPUs 情況。

設置 NumaNode0 上的 8 個 CPU 用于 I/O,其他 3 個節點用于 Processor。

Scheduler 負責根據需求創建和銷毀 Worker,一個 Worker 即可是一個 Thread 也可以是一個 Fiber,可以通過 Max Worker Threads 和 Use Windows Fibers 配置項來進行設置。

Max Worker Threads 選項負責限制線程池(Threading Pool)中線程的最大數量。

SELECT *
FROM sys.configurations
WHERE [name] LIKE '%worker%';

默認值為 0,即允許 SQL Server 根據 CPU 和版本情況進行自動配置最大線程數量。

 Number of CPUs

 32-bit Computor 

 64-bit Computor 

 <= 4 processors 

 256

 512

8 processors

 288

 576

 16 processors

 352

 704

 32 processors

 480

 960

 64 processors

 736

 1472

可以使用 sp_configure 來配置該選項。

EXEC sp_configure 'show advanced options', 1;
GO
RECONFIGURE;
GO

EXEC sp_configure 'max worker threads', 900;
GO
RECONFIGURE;
GO

使用如下 SQL 查詢來查看當前數據庫環境中的 Max Workers Count 和 Current Workers Count。

SELECT max_workers_count FROM sys.dm_os_sys_info;
SELECT SUM(current_workers_count) AS current_workers_count FROM sys.dm_os_schedulers;

Worker 直接使用 Scheduler,每個 Worker 只會關聯到 1 個 Scheduler,Worker 不能從一個 Scheduler 轉移到另一個 Scheduler 上。

Worker 處理的工作單元可以是一個 Request,也可以是一個 Task。比如批處理 Request 可能被分解成多個 Task。當 Scheduler 接收到新的 Request 或 Task 請求時,如果當前沒有空閑 Worker(Idle Worker),則根據配置開始創建新的 Worker,而 Request 或 Task 將被綁定到該 Worker 上。

SELECT is_idle
    ,COUNT(*) AS [count]
FROM sys.dm_os_schedulers
WHERE scheduler_id < 255
    AND is_online = 1
GROUP BY is_idle;

sys.dm_os_schedulers 中的 scheduler_id < 255 則為常規查詢,如果 scheduler_id >= 255 則為系統內調度。

如果 Worker 已經空閑了至少 15 分鐘以上,或者 SQL Server 檢測到有內存壓力時,空閑的 Worker 可能被銷毀。

  • 在 32 位機上,1 個 Worker 至少占用 0.5M 的內存。
  • 在 64 位機上,1 個 Worker 至少占用 2M 的內存。

所以,銷毀空閑的 Worker 以釋放內存可以立即改善系統對內存的迫切需求。

SQL Server 設計了非常高效的 Worker Pool,所以即使有大量的并發在訪問數據庫,可能 Worker Pool 的大小仍遠小于配置的 Max Worker Threads 的值。但盡管如此,如果 Worker 中處理的 Task 發生了鎖定或者等待 IO 完成等阻塞操作,Worker 即會被阻塞,Worker 不會其他任何請求直到阻塞條件解除。

SELECT AVG(current_workers_count) AS [avg_current_workers_count]
    ,AVG(active_workers_count) AS [avg_active_workers_count]
    ,MAX(current_workers_count) AS [max_current_workers_count]
    ,MAX(active_workers_count) AS [max_active_workers_count]
    ,SUM(current_workers_count) AS [total_current_workers_count]
    ,SUM(active_workers_count) AS [total_active_workers_count]
    ,SUM(pending_disk_io_count) AS [total_pending_disk_io_count]
FROM sys.dm_os_schedulers
WHERE scheduler_id < 255
    AND is_online = 1;

SQL Server 中的 Session 實際上只描述了建立連接后的通道,通過該通道可以發送 Request,通道也可以保持空閑。所以 Session 不會與特定的 Scheduler 進行綁定。

SELECT s.session_id
    ,r.command
    ,r.[status]
    ,r.wait_type
    ,r.scheduler_id
    ,w.is_preemptive
    ,t.task_state
    ,u.cpu_id
FROM sys.dm_exec_sessions AS s
INNER JOIN sys.dm_exec_requests AS r ON s.session_id = r.session_id
INNER JOIN sys.dm_os_tasks AS t ON r.task_address = t.task_address
INNER JOIN sys.dm_os_workers AS w ON t.worker_address = w.worker_address
INNER JOIN sys.dm_os_schedulers AS u ON t.scheduler_id = u.scheduler_id
WHERE s.is_user_process = 0
ORDER BY r.scheduler_id;

當 Session 建立后,會將當前負載最低的 Scheduler 分配給該 Session。然后,當 Session 中有新的 Request 抵達時,SQL Server 會將最近處理過該 SPID 中 Request 的 Scheduler 作為推薦的調度器(Preferred Scheduler)優先調度。盡管如此,當 Session 中抵達的 Request 開始排隊時,SQL Server 會計算每個 Scheduler 的 Load Factor,尋找負載最低的 Scheduler 來處理任務。

 

《人人都是 DBA》系列文章索引:

 序號 

 名稱 

1

 人人都是 DBA(I)SQL Server 體系結構

2

 人人都是 DBA(II)SQL Server 元數據

3

 人人都是 DBA(III)SQL Server 調度器

4

 人人都是 DBA(IV)SQL Server 內存管理

5

 人人都是 DBA(V)SQL Server 數據庫文件

6

 人人都是 DBA(VI)SQL Server 事務日志

7

 人人都是 DBA(VII)B 樹和 B+ 樹

8

 人人都是 DBA(VIII)SQL Server 頁存儲結構

9

 人人都是 DBA(IX)服務器信息收集腳本匯編

10

 人人都是 DBA(X)資源信息收集腳本匯編

11

 人人都是 DBA(XI)I/O 信息收集腳本匯編

12

 人人都是 DBA(XII)查詢信息收集腳本匯編

13

 人人都是 DBA(XIII)索引信息收集腳本匯編

14

 人人都是 DBA(XIV)存儲過程信息收集腳本匯編 

15

 人人都是 DBA(XV)鎖信息收集腳本匯編

本系列文章《人人都是 DBA》由 Dennis Gao 發表自博客園個人技術博客,未經作者本人同意禁止任何形式的轉載,任何自動或人為的爬蟲轉載或抄襲行為均為耍流氓。


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()