人人都是 DBA(III)SQL Server 调度器
在 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 |
|
|
2 |
|
|
3 |
|
|
4 |
|
|
5 |
|
|
6 |
|
|
7 |
|
|
8 |
|
|
9 |
|
|
10 |
|
|
11 |
|
|
12 |
|
|
13 |
|
|
14 |
|
|
15 |
本系列文章《人人都是 DBA》由 Dennis Gao 发表自博客园个人技术博客,未经作者本人同意禁止任何形式的转载,任何自动或人为的爬虫转载或抄袭行为均为耍流氓。
人人都是 DBA(III)SQL Server 调度器的更多相关文章
- 人人都是 DBA(VIII)SQL Server 页存储结构
当在 SQL Server 数据库中创建一张表时,会在多张系统基础表中插入所创建表的信息,用于管理该表.通过目录视图 sys.tables, sys.columns, sys.indexes 可以查看 ...
- 人人都是 DBA(VI)SQL Server 事务日志
SQL Server 的数据库引擎通过事务服务(Transaction Services)提供事务的 ACID 属性支持.ACID 属性包括: 原子性(Atomicity) 一致性(Consisten ...
- 人人都是 DBA(V)SQL Server 数据库文件
SQL Server 数据库安装后会包含 4 个默认系统数据库:master, model, msdb, tempdb. SELECT [name] ,database_id ,suser_sname ...
- 人人都是 DBA(IV)SQL Server 内存管理
SQL Server 的内存管理是一个庞大的主题,涉及特别多的概念和技术,例如常见的 Plan Cache.Buffer Pool.Memory Clerks 等.本文仅是管中窥豹,描述常见的内存管理 ...
- 人人都是 DBA(II)SQL Server 元数据
SQL Server 中维护了一组表用于存储 SQL Server 中所有的对象.数据类型.约束条件.配置选项.可用资源等信息,这些信息称为元数据信息(Metadata),而这些表称为系统基础表(Sy ...
- 人人都是 DBA(I)SQL Server 体系结构
在了解 SQL Server 数据库时,可以先从数据库的体系结构来观察.SQL Server 的体系结构中包含 4 个主要组成部分: 协议层(Protocols) 关系引擎(Relational En ...
- 人人都是 DBA(XII)查询信息收集脚本汇编
什么?有个 SQL 执行了 8 秒! 哪里出了问题?臣妾不知道啊,得找 DBA 啊. DBA 人呢?离职了!!擦!!! 程序员在无处寻求帮助时,就得想办法自救,努力让自己变成 "伪 DBA& ...
- 人人都是 DBA(XV)锁信息收集脚本汇编
什么?有个 SQL 执行了 8 秒! 哪里出了问题?臣妾不知道啊,得找 DBA 啊. DBA 人呢?离职了!!擦!!! 程序员在无处寻求帮助时,就得想办法自救,努力让自己变成 "伪 DBA& ...
- 人人都是 DBA(XIV)存储过程信息收集脚本汇编
什么?有个 SQL 执行了 8 秒! 哪里出了问题?臣妾不知道啊,得找 DBA 啊. DBA 人呢?离职了!!擦!!! 程序员在无处寻求帮助时,就得想办法自救,努力让自己变成 "伪 DBA& ...
随机推荐
- Oracle 服务器端执行带参数的procedure
进入服务器后 su - oracle sqlplus schema/schemapass 连接上以后,输入以下,然后执行 declare vRet number(5) := 8; begin proc ...
- JSTL和EL
JSTL和EL 1.EL表达式总是放在大括号里,而且前面有一个美元符前缀. person.name2.相似点:(1).都可以让我们在静态内蓉中插入动态信息.EL:室外温度是{emp}度 JSP:室外温 ...
- pd name与comment互换,或者code互换,总之互换
1 PowerDesigner中批量根据对象的name生成comment的脚本 执行方法:Open PDM -- Tools -- Execute Commands -- Run Script Opt ...
- nginx下搭建 Yii框架
因为启用了rewrite,导致css,js,images等静态文件也定向到index.php 我不得不重定向静态文件的路径 仅供参考: server { listen 80; server_name ...
- 面向对象程序设计 第二次作业<1>
Github链接:https://github.com/zora02/object-oriented/tree/master/1001.A%2BB%20Format%20(20) 一.解题 题目 解题 ...
- 健忘vs总结
上周入职新公司,报道之前自己也曾想过要从头开始,用一个新的精神面貌来迎接新的起点,培养一些新的习惯. 周四是15日,新公司的发薪日(当然还没有我的份~),小组群内一个刚毕业的新人兴冲冲的说终于领到第一 ...
- 一个豆瓣API的使用——拒绝思维定式
好久没写博客了,最近一直在用豆瓣API爬数据,不知道以前的是什么样,毕竟刚开始用没多久,就用最新的V2版本,以前的不更新了,可以参照https://developers.douban.com/wiki ...
- 解决Canvas.toDataURL 图片跨域问题
如题,在将页面的图片地址进行本地输出时(Html2Canvas.js),因不同源存在跨域问题,会出现toDataURL访问权限问题: [Redirect at origin 'http://sub1. ...
- 获取基于Internet Explorer_Server的聊天窗口内容
假设在得到窗体中控件的句柄(通过SPY++)的前提下,如果是像文本框这种控件,只要用SendMessage就可得到文本了,但是对于聊天记录窗口却行不通(返回空值),因为那其实是一个内置浏览器Inter ...
- VS2012中,C# 配置文件读取 + C#多个工程共享共有变量 + 整理using语句
(一) C# 配置文件读取 C#工程可以自动生成配置文件,以便整个工程可以使用设置的配置进行后续的处理工作. 1. 首先,右键工程文件-->Properties -->settings-- ...