SQLOS任务调度算法
前些天在处理一个SQL Server LATCH导致的数据库停止响应问题时,遇到了一些需要SQLOS调度知识解决的问题,正好以前看过一篇官网的文章,在这里稍作修改贴出来。
原文网址如下:
https://blogs.msdn.microsoft.com/apgcdsd/2011/11/23/sql-server-sqlos/
【介绍】
SQL Server在通过BATCH,TASK,WORKER,SCHEDULER等来对任务进行调度和处理。了解这些概念,对于了解SQL Server内部是如何工作,是非常有帮助的。
通常来讲,SCHEDULER个数是跟CPU个数相匹配的。除了几个系统的SCHEDULER以外,每一个SCHEDULER都映射到一个CPU,如下面的查询结果所示,我们有四个CPU,也就有相应四个USER SCHEDULER,而scheduler_total_count有16个则是因为有8个是系统scheduler,我们一般不必关注系统scheduler。
select cpu_count,scheduler_count,scheduler_total_count from sys.dm_os_sys_info
而WORKER(又称为WORKER THREAD), 则是工作线程。在一台服务器上,我们可以有多个工作线程。因为每一个工作线程要耗费资源,所以,SQL Server有一个最大工作线程数。
TASK是worker的使用者,每个TASK系统会给它分配一个工作线程进行处理,是一对一的关系但并不绑定。如果所有的工作线程都在忙,而且已经达到了最大工作线程数,SQL Server就要等待,直到有一个忙的工作线程被释放。
最大工作线程数可以通过下面的查询得到。SQL SERVER并不是一开始就把这些所有的工作线程都创建,而是依据需要而创建。
select cpu_count,max_workers_count from sys.dm_os_sys_info
一个客户端connection可能包含一个或多个BATCH,一般SQL Server引擎会为一个BATCH视为一个TASK,但使用并行化查询的BATCH会被分解成多个TASK。具体BATCH怎么分解成TASK,以及分解成多少个,则是由SQL Server内部决定的。但是在这里我们依然可以使用相关DMV探寻一下大致分配情况:
我们使用spid为63的窗口执行一个复杂的查询,此查询使用默认并行度运行(由于有8个CPU因此默认MAXDOP=8)。
select * from sys.dm_os_tasks where session_id=63 order by 7
结果如下:
(33 行受影响)
task_address task_state context_switches_count pending_io_count pending_io_byte_count pending_io_byte_average scheduler_id session_id exec_context_id request_id worker_address host_address parent_task_address
------------------ ---------------------------------- ---------------- --------------------- ----------------------- ------------ ---------- --------------- ----------- ------------------ ------------------ -------------------
0x000000000DB29468 SUSPENDED 4696 510 0 0 0 63 7 0 0x0000000032E02160 0x0000000000000000 0x0000000025E67468
0x000000000DB29088 SUSPENDED 1457 290 0 0 0 63 11 0 0x0000000017FE2160 0x0000000000000000 0x0000000025E67468
0x0000000012358CA8 RUNNING 1937 1945 0 0 0 63 21 0 0x0000000034E84160 0x0000000000000000 0x0000000025E67468
0x0000000012359088 SUSPENDED 2 0 0 0 0 63 32 0 0x000000000685A160 0x0000000000000000 0x0000000025E67468
0x000000000F20D468 SUSPENDED 4489 510 0 0 1 63 4 0 0x000000001FE30160 0x0000000000000000 0x0000000025E67468
0x0000000035F19468 SUSPENDED 1731 290 0 0 1 63 16 0 0x00000002BD8DC160 0x0000000000000000 0x0000000025E67468
0x0000000035F19088 SUSPENDED 2280 1864 0 0 1 63 23 0 0x000000001AA60160 0x0000000000000000 0x0000000025E67468
0x0000000035F18CA8 SUSPENDED 9 0 0 0 1 63 28 0 0x00000002BB60A160 0x0000000000000000 0x0000000025E67468
0x000000002E283468 SUSPENDED 4485 510 0 0 2 63 5 0 0x000000001FE48160 0x0000000000000000 0x0000000025E67468
0x000000001A736108 SUSPENDED 1700 290 0 0 2 63 15 0 0x00000000310C6160 0x0000000000000000 0x0000000025E67468
0x000000001A737468 RUNNING 2256 1865 0 0 2 63 20 0 0x00000000049DC160 0x0000000000000000 0x0000000025E67468
0x000000001A737848 SUSPENDED 5 0 0 0 2 63 30 0 0x0000000018390160 0x0000000000000000 0x0000000025E67468
0x000000001A609088 SUSPENDED 3973 510 0 0 3 63 8 0 0x000000001BEC0160 0x0000000000000000 0x0000000025E67468
0x0000000014A49848 SUSPENDED 1652 290 0 0 3 63 14 0 0x0000000017436160 0x0000000000000000 0x0000000025E67468
0x0000000014A49088 RUNNING 2058 1878 0 0 3 63 18 0 0x0000000025D2C160 0x0000000000000000 0x0000000025E67468
0x000000000FD5C108 SUSPENDED 6 0 0 0 3 63 26 0 0x00000000213DA160 0x0000000000000000 0x0000000025E67468
0x0000000025E67468 SUSPENDED 3 0 0 0 4 63 0 0 0x00000000353A6160 0x0000000000000000 NULL
0x0000000006EC9C28 SUSPENDED 4469 510 0 0 4 63 6 0 0x000000002AF14160 0x0000000000000000 0x0000000025E67468
0x000000001C0708C8 SUSPENDED 1725 290 0 0 4 63 13 0 0x000000002AC74160 0x0000000000000000 0x0000000025E67468
0x000000001C0704E8 RUNNING 2324 1889 0 0 4 63 24 0 0x000000001497A160 0x0000000000000000 0x0000000025E67468
0x0000000012035468 SUSPENDED 5 0 0 0 4 63 29 0 0x00000002B70E6160 0x0000000000000000 0x0000000025E67468
0x00000002BB1144E8 SUSPENDED 4084 511 0 0 5 63 1 0 0x0000000028F4E160 0x0000000000000000 0x0000000025E67468
0x00000002BB115C28 SUSPENDED 1775 290 0 0 5 63 12 0 0x000000000E7B4160 0x0000000000000000 0x0000000025E67468
0x00000002BB115468 RUNNABLE 2256 1830 0 0 5 63 22 0 0x000000000AC4C160 0x0000000000000000 0x0000000025E67468
0x000000000BBA5848 SUSPENDED 5 0 0 0 5 63 27 0 0x000000002ABFC160 0x0000000000000000 0x0000000025E67468
0x00000000263BFC28 SUSPENDED 5031 510 0 0 6 63 2 0 0x000000002E444160 0x0000000000000000 0x0000000025E67468
0x00000002BE5D6108 SUSPENDED 1856 290 0 0 6 63 10 0 0x00000002BF20E160 0x0000000000000000 0x0000000025E67468
0x0000000020446CA8 RUNNING 2275 1936 0 0 6 63 19 0 0x0000000005104160 0x0000000000000000 0x0000000025E67468
0x0000000020446108 SUSPENDED 5 0 0 0 6 63 31 0 0x0000000022F9E160 0x0000000000000000 0x0000000025E67468
0x000000003193B468 SUSPENDED 4276 510 0 0 7 63 3 0 0x000000002B58C160 0x0000000000000000 0x0000000025E67468
0x000000003193A8C8 SUSPENDED 1806 290 0 0 7 63 9 0 0x000000001FCEA160 0x0000000000000000 0x0000000025E67468
0x000000000E2A2CA8 SUSPENDED 2308 2007 0 0 7 63 17 0 0x00000000113AE160 0x0000000000000000 0x0000000025E67468
0x000000000E2A28C8 SUSPENDED 10 0 0 0 7 63 25 0 0x000000002504C160 0x0000000000000000 0x0000000025E67468
从上图我们可以看到,来自客户端的一个BACTH由于并行查询而被分解成了33个TASK,对应33个task_address,和33个worker_address,这说明一个BATCH占用了33个worker threads,这个数目是相当大的。由于本例中USER SCHEDULER的数目是8,因此默认MAXDOP也是8,所以我们看到有编号为0-7的8个scheduler_id,其中scheduler_id为4的CPU被5个task占用,这5个task当中有一个parent_task_address为NULL,说明这个task是整个BATCH的主task。其他7个CPU上都只有4个task。如果观察时间更长一点我们还会发现,同一个CPU上的4个task只有exec_context_id倒数第二大的task是一直处于running状态的,其他的全部是处于占用worker thread的suspended状态。
【关系】
我们初步了解了Connection, Batch, Task, Worker, Scheduler, CPU这些概念,那么,它们之间的关系到底是怎么样呢?
如上图所示,左边是很多连接,每个连接有一个相应的SPID,只要用户没有登出,或者没有timeout,这个始终是存在的。标准设置下,对于用户连接数目,是没有限制的。
在每一个连接里,我们可能会有很多batch,在一个连接里,batch都是按顺序的。只有一个batch执行完了,才会执行下面一个batch。因为有很多连接,所以从SQL Server层面上看,同时会有很多个batch。
SQL Server会做优化,每一个batch,可能会分解成多个task以支持如并行查询。这样,在SQL层面上来看,同时会有很多个TASK。
SQL Server上,每一个CPU通常会对应一个Scheduler,有几个额外的系统的Scheduler,只是用来执行一些系统任务。对用户来讲,我们只需要关心User Scheduler就可以了。如果有4个CPU的话,那么通常就会有4个User Scheduler。
每个Scheduler上,可以有多个worker对应。Worker是真正的执行单元,Scheduler(对CPU的封装)是执行的地方。Worker的总数受max worker thread限制。每一个worker在创建的时候,自己需要申请2M内存空间。如果max worker thread为1024,并且那些worker全部创建的话,至少需要2G空间。所以太多的worker,会占用很多系统资源。
【跟踪】
在了解Connection, Batch, Task, Worker, Scheduler, CPU之间的关系后,下面我们用DMV跟踪一下运作的流程。
步骤一:
执行下面的脚本,创建一个测试数据库和测试数据表
CREATE DATABASE TEST
go
use TEST
go
CREATE TABLE TEST(ID int,name nvarchar(50))
INSERT INTO TEST VALUES (1, 'aaa')
步骤二:
打开一个查询窗口,执行下面的语句,注意,我们这里并没有commit transaction.
begin tran
update TEST set name='bbb' where [ID] = 1
步骤三:
打开另外一个窗口,执行下面的语句,我们会看到,下面的查询会一直在执行,因为我们前面的一个transaction并没有关闭。从查询窗口,我们可以看到,下面语句执行的SPID为58
SELECT * FROM TEST
步骤四:查看连接
从下面的查询来看,我们的连接对应的SPID是58,被block住了。
步骤五:查看batch
我们查看SQL Profiler, 看到我们的Batch是SELECT * FROM TEST
步骤六:查看TASK
用下面的DMV, 我们可以看到,针对SESSION_ID=58的,只有一个task. (地址为0x0064F048), 而针对该TASK的worker地址为: 0x803081A0。同时我们也可以看到该worker运行在Scheduler 0上面。
步骤七:查看WORKER
从下面的查询可以知道,这个WORKER已经执行了5291个task了。这个worker相应的Scheduler地址是0x00932080
步骤八:查看SCHEDULER
从下面的查询可以得知,Scheduler_address (0x00932080) 相应的CPU_ID是0。在我们的系统上,有4个CPU, 编号分别为0, 1, 2, 3. 但是有7个SCHEDULER, 其中3个是SYSTEM SCHEDULER, 4个是USER SCHEDULER。在每个SCHEDULER上,有相应的WORKER数目。因为WORKER是根据需要而创建的,所以,在每个SCHEDULER上,目前WORKER数目很少。而且其中有些WORKER还处于SLEEPING状态。
【应用】
我们了解了SQL SERVER任务调度的机制,那么有些问题,就会更加清楚。
设置MAXDOP的作用。MAXDOP=1的话,可以使得一个BATCH只对应一个TASK。如果一个BATCH产生多个TASKS,那么TASK之间的协调,等待等等,将是很大的开销。把MAXDOP设小,能同时减少WORKER的使用量。所以,如果我们看到等待类型为CXPACKET的话,那么我们可以设置MAXDOP,减少并行度。
比较大的SPID。如果我们看到SPID的号码非常大,如超过1000,那么通常表明,我们系统有很严重的BLOCKING。SQL SERVER不对连接数做限制,但是对于WORKER数,是有限制的。缺省情况下,最大个数如下:
Number of CPUs |
32bit |
64 bit |
<=4 processors |
256 |
512 |
8 processors |
288 |
576 |
16 processors |
352 |
704 |
32 processors |
480 |
960 |
对于很大的SPID编号,通常表明,我们的WORKER数是很高的。这种情况比较危险,如果一个新的连接进来,可能没有空闲WORKER来处理这个连接。在CLUSTER环境下,ISALIVE检查会失败,会导致SQL SERVER做FAILOVER。
NON-YIELDING SCHEDULER错误。我们有时候会看到SQL Server会报一个17883错误, NON-YIELDING SCHEDULER。这个错误指的是,在一个SCHEDULER上,会有多个WORKER,它们以友好的方式,互相占用一会儿SCHEDULER资源。某个WORKER占用SCHEDULER后,执行一段时间,会做YIELD,也就是退让,把SCHEDULER资源让出来,让其他WORKER去使用。如果某一个WORKER出于某种原因,不退让SCHEDULER资源,导致其他WORKER没有机会运行,这种现象叫NON-YIELDING SCHEDULER。出现这种情况,SQL SERVER有自动检测机制,会打一个DUMP出来。我们需要进一步分析DUMP为什么该WORKER不会YIELD。
WORKER 用完。我们可以做一个小实验。我们在一台32位机器上,创建上面提及的测试数据库,并且,开启一个同样的未关闭transaction的update语句。
然后执行下面的程序。下面的程序会开启256个连接到SQL Server, 这256个连接由于前面的transaction未闭合,都处于BLOCKING状态。
using System;
using System.Diagnostics;
namespace WORKER
{class Program{static void Main(string[] args){for(int i=0; i<256; i++){OpenConnection();}}static void OpenConnection(){ProcessStartInfo startInfo = new ProcessStartInfo();startInfo.FileName = "sqlcmd.exe";startInfo.Arguments = " -E -S SERVERNAME -d TEST -q \" SELECT * FROM TEST \"";Process.Start(startInfo);}}
}
查询SELECT * FROM sys.dm_os_tasks这时候我们发现有278个TASK,而查询sys.dm_os_schedulers 我们发现有两个CPU, 因此有两个用户SCHEDULER, 每个SCHEDULER上,有128个workers. 加起来有256个WORKERS。针对两个CPU的架构,我们缺省最大的WORKER数是256。所以已经到了极限了。
这时候,我们新开启一个连接,会发现SQL Server连不上,并报如下错误:
这是因为WORKER用完的缘故。新的连接无法获得一个WORKER来做login process。所以导致连接失败。在群集环境下,如果连接不上SQL Server, ISALIVE检查会失败,会引起SQL Server FAILOVER。所有的连接都会被强迫中止,并且SQL Server会在新结点上重新启动。针对这种情况,我们可以修改提高MAX WORKER THREAD,但是并不能最终解决问题,由于BLOCKING缘故,新的连接会迅速积累,一直把MAX WORKER THREAD用完,所以这时候,我们应该检查BLOCKING。使得task能及时完成,释放WORKER。
【总结】
SQL Server的任务调度使得SQL SERVER能够以最快方式处理用户发过来的请求。了解SQL SERVER的任务调度过程,对于我们调整系统性能是非常有帮助的。如适当增加MAX WORKER THREAD,调整MAXDOP,去除BLOCKING等等,了解这些概念,会使得我们的调整更有目的性。
转载于:https://www.cnblogs.com/leohahah/p/7473757.html
SQLOS任务调度算法相关推荐
- Timeout occurred while waiting for latch: class 'ACCESS_METHODS_DATASET_PARENT'
前些天某个SQL Server数据库的错误日志爆出如下错误: Timeout occurred while waiting for latch: class 'ACCESS_METHODS_DATAS ...
- c语言链表最高响应比优先,操作系统--最高响应比优先调度算法实验报告..doc
操作系统--最高响应比优先调度算法实验报告. 进程调度一.实验题目与要求 编写程序完成批处理系统中的作业调度,要求采用响应比高者优先的作业调度算法.实现具体包括:首先确定作业控制块的内容和组成方式:然 ...
- LVS原理详解(3种工作方式8种调度算法)--老男孩
一.LVS原理详解(4种工作方式8种调度算法) 集群简介 集群就是一组独立的计算机,协同工作,对外提供服务.对客户端来说像是一台服务器提供服务. LVS在企业架构中的位置: 以上的架构只是众多企业里面 ...
- 据说程序员等电梯的时候都想过调度算法
作者:SUN's Cabin 链接:https://www.cnblogs.com/jianyungsun/archive/2011/03/16/1986439.html 1.传统电梯调度算法 1.1 ...
- linux中O(1)调度算法与全然公平(CFS)调度算法
一.O(1)调度算法 1.1:优先级数组 O(1)算法的:一个核心数据结构即为prio_array结构体. 该结构体中有一个用来表示进程动态优先级的数组queue,它包括了每一种优先级进程所形成的链表 ...
- 负载均衡集群介绍、LVS介绍、LVS调度算法、 LVS NAT模式搭建
负载均衡集群介绍 LVS介绍 lvs的NAT模式介绍 这种模式借助iptables的nat表来实现,用户的请求到分发器后,通过预设的iptables规则,把请求的数据包转发到后端的服务器上去,这些服务 ...
- http反向代理调度算法追朔
标题索引 追朔原因 反代原理 调度算法 算法评估 追朔原因 http调度算法有多种,在nginx.haproxy.apache.keepalive中等等都有相对应的算法,但是算法根本原理是不变的 反代 ...
- 抢占式优先权调度算法
在这种方式下,系统同样是把处理机分配给优先权最高的进程,使之执行.但在其执行期间,只要又出现了另一个其优先权更高的进程,进程调度程序就立即停止当前进程(原优先权最高的进程)的执行,重新将处理机分配给新 ...
- 先来先服务调度算法(FCFS)
先来先服务(FCFS)调度算法是一种最简单的调度算法,该算法既可用于作业调度,也可用于进程调度.当在作业调度中采用该算法时,每次调度都是从后备作业队列中选择一个或多个最先进入该队列的作业,将它们调入内 ...
最新文章
- 在 C# 中通过 P/Invoke 调用Win32 DLL
- Confluence 6 配置文件和key
- SNS网站是否应该实行邀请制、实名制?
- iOS开发基础知识--碎片44
- php mysql 非扫描,PHP的中使用非缓冲模式查询数据库的方法
- codesoft各个版本的 dll_win10安装pytorch-gpu版本
- 微信公众平台开发之微信access_token如何有效长期保存
- Java NIO使用及原理分析(二)
- cf807 c 二分好题
- .NET Core 2.0 单元测试中初识 IOptionsMonitoramp;lt;Tamp;gt;
- Microsoft规划了.NET的未来发展
- php中日期选择代码,实现JS日期时间选择器
- Jenkins-Pipeline 流水线发布
- SCCM2012系列之十,SCCM2012软件分发
- attachEvent传递给其handler的一个默认参数
- 用python简单处理图片(3):添加水印
- C# EF6 更新对象
- 简单好用的桌面隐藏工具:Desktop Curtain for Mac
- juce开发vst配置
- 2020年的5种常见骇客行为,你的电脑安全吗?
热门文章
- 计算广告之淘宝oCPC智能出价
- linux 秒数转时间,linux下如何把时间转成秒数,或把秒数转换成标准时间格式
- c#控制台实现计算器二目运算功能
- html怎么安装系统,一键重装系统_MBR分区一键安装系统教程-爱纯净
- oracle根据关键字搜索存储过程
- android x86安装到硬盘不能启动,PC下安装androidx86一些问题的解决方法,gui start
- Firefox 不知道如何打开此地址,因为协议 (javascrpit) 未和任何程序关联.
- java接口与抽象类的异同
- 什么是人工智能?你需要知道的关于人工智能的一切
- 直男福利!手把手教你做一只口红色号识别器,秒变李佳琦