SqlServer基础--SQLOS 的任务调度(转)

本文涉及的产品
云数据库 RDS SQL Server,基础系列 2核4GB
RDS SQL Server Serverless,2-4RCU 50GB 3个月
推荐场景:
简介:
【介绍】
SQL Server 通过 WORKER, SCHEDULER, TASK 等来对任务进行调度和处理。了解这些概念,对于了解 SQL Server 内部是如何工作,是非常有帮助的。
通常来讲, SCHEDULER 个数是跟 CPU 个数相匹配的 。除了几个系统的 SCHEDULER 以外,每一个 SCHEDULER 都映射到一个 CPU ,如下面的查询结果所示,我们有四个 CPU ,也就有相应四个 SCHEDULER
SELECT cpu_count,scheduler_count,scheduler_total_count,max_workers_count FROM sys.dm_os_sys_info
WORKER ( 又称为 WORKER THREAD), 则是工作线程。在一台服务器上,我们可以有多个工作线程。因为每一个工作线程要耗费资源,所以, SQL Server 有一个最大工作线程数。一个 TASK 进来,系统会给它分配一个工作线程进行处理。但是当所有的工作线程都在忙,而且已经达到了最大工作线程数, SQL Server 就要等待,直到有一个忙的工作线程被释放。最大工作线程数可以通过下面的查询得到。 SQL SERVER 并不是一开始就把这些所有的工作线程都创建,而是依据需要而创建。
SELECT cpu_count,scheduler_count,scheduler_total_count,max_workers_count FROM sys.dm_os_sys_info
TASK 是由 BATCH 而来。我们知道,一个连接,可以包含多个 BATCH ,而每个 BATCH 则可以分解成多个 TASK 。如下面某一个连接要做的事情。这个连接要做的有两个 BATCH ,而每个 BATCH ,如 SELECT * FROM TABLE_B ,因为可以支持并行化查询,所以可能会被分解成多个 TASK 。具体 BATCH 怎么分解成 TASK ,以及分解成多少个,则是由 SQL Server 内部决定的。
INSERT INTO TABLE_B VALUES (‘aaa’)
GO
SELECT * FROM TABLE_B
GO
【关系】
我们初步了解了 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 Test4;
GO
USE Test4;
GO
CREATE TABLE Test
(ID INT,
name NVARCHAR(50)
);
INSERT INTO Test
VALUES(1,'aaa');
步骤二:
打开一个查询窗口,执行下面的语句,注意,我们这里并没有 commit transaction.
USE Test4
BEGIN TRAN;
UPDATE Test SET name = 'bbb'
WHERE [ID] = 1;
步骤三:
打开另外一个窗口,执行下面的语句,我们会看到,下面的查询会一直在执行,因为我们前面的一个 transaction 并没有关闭。从查询窗口,我们可以看到,下面语句执行的 SPID 58
USE Test4
SELECT * FROM Test
步骤四:查看连接。
从下面的查询来看,我们的连接对应的 SPID 58 ,被 block 住了。
SELECT * FROM sys.sysprocesses where spid=56
步骤五:查看 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
SELECT * FROM sys.dm_os_tasks where session_id=56
步骤八:查看 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 状态。
SELECT * FROM sys.dm_os_schedulers
【应用】
我们了解了 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

PS C:\WINDOWS\system32> sqlcmd.exe /?
Microsoft (R) SQL Server Command Line Tool
Version 11.0.2100.60 NT x64
Copyright (c) 2012 Microsoft. All rights reserved.
usage: Sqlcmd [-U login id] [-P password]
[-S server] [-H hostname] [-E trusted connection]
[-N Encrypt Connection][-C Trust Server Certificate]
[-d use database name] [-l login timeout] [-t query timeout]
[-h headers] [-s colseparator] [-w screen width]
[-a packetsize] [-e echo input] [-I Enable Quoted Identifiers]
[-c cmdend] [-L[c] list servers[clean output]]
[-q "cmdline query"] [-Q "cmdline query" and exit]
[-m errorlevel] [-V severitylevel] [-W remove trailing spaces]
[-u unicode output] [-r[0|1] msgs to stderr]
[-i inputfile] [-o outputfile] [-z new password]
[-f <codepage> | i:<codepage>[,o:<codepage>]] [-Z new password and exit]
[-k[1|2] remove[replace] control characters]
[-y variable length type display width]
[-Y fixed length type display width]
[-p[1] print statistics[colon format]]
[-R use client regional setting]
[-K application intent]
[-M multisubnet failover]
[-b On error batch abort]
[-v var = "value"...] [-A dedicated admin connection]
[-X[1] disable commands, startup script, environment variables [and exit]]
[-x disable variable substitution]
[-? show syntax summary]

sqlcmd.exe -U sa -P 123456 -S localhost -d Test4 -q " SELECT * FROM TEST "
【总结】
SQL Server 的任务调度使得 SQL SERVER 能够以最快方式处理用户发过来的请求。了解 SQL SERVER 的任务调度过程,对于我们调整系统性能是非常有帮助的。如适当增加 MAX WORKER THREAD ,调整 MAXDOP ,去除 BLOCKING 等等,了解这些概念,会使得我们的调整更有目的性。
相关实践学习
使用SQL语句管理索引
本次实验主要介绍如何在RDS-SQLServer数据库中,使用SQL语句管理索引。
SQL Server on Linux入门教程
SQL Server数据库一直只提供Windows下的版本。2016年微软宣布推出可运行在Linux系统下的SQL Server数据库,该版本目前还是早期预览版本。本课程主要介绍SQLServer On Linux的基本知识。 相关的阿里云产品:云数据库RDS&nbsp;SQL Server版 RDS SQL Server不仅拥有高可用架构和任意时间点的数据恢复功能,强力支撑各种企业应用,同时也包含了微软的License费用,减少额外支出。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/sqlserver
目录
相关文章
|
7月前
|
SQL 监控 数据库
【SQLserver】常见问题和解决方案
【SQLserver】常见问题和解决方案
113 0
|
5月前
|
开发框架 前端开发 关系型数据库
ABP框架使用Mysql数据库,以及基于SQLServer创建Mysql数据库的架构和数据
ABP框架使用Mysql数据库,以及基于SQLServer创建Mysql数据库的架构和数据
|
7月前
|
关系型数据库 MySQL 数据库
实时计算 Flink版操作报错合集之sqlserver mysql都用的胖包,sqlserver的成功了,mysql报这个错如何解决
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
302 6
|
SQL 数据库 流计算
flink-connector-sqlserver-cdc支持SQL server的内存优化表
flink-connector-sqlserver-cdc支持SQL server的内存优化表
142 1
|
SQL Oracle 前端开发
基于多数据源零代码同时生成多个数据库CRUD增删改查RESTful API接口——MySql,PostgreSql,Oracle,Microsoft SQL Server
利用spring boot多数据源功能,可以同时支持不同类型数据库mysql,oracle,postsql,sql server等,以及相同类型数据库不同的schema。零代码同时生成不同类型数据库增删改查RESTful api,且支持同一接口中跨库数据访问二次开发。在同一个Java程序中,通过多数据源功能,不需要一行代码,我们就可以得到不同数据库的基本crud功能,包括API和UI。
192 0
基于多数据源零代码同时生成多个数据库CRUD增删改查RESTful API接口——MySql,PostgreSql,Oracle,Microsoft SQL Server
|
SQL 关系型数据库 数据库
Cloud Toolkit 数据库 SQL 执行器
Cloud Toolkit是一个IDE 插件,帮助开发者更高效地开发、测试、诊断并部署应用。 使用本插件,开发者能够方便地将本地应用一键部署到任意机器,或 ECS、EDAS、Kubernetes; 并支持高效执行终端命令和 SQL 等。
4599 8
|
SQL 关系型数据库 数据库
sqlserver中几种典型的等待
为了准备今年的双11很久没有更新blog,在最近的几次sqlserver问题的排查中,总结了sqlserver几种典型的等待类型,类似于oracle中的等待事件,如果看到这样的等待类型时候能够迅速定位问题的根源,下面通过一则案例来把这些典型的等待处理方法整理出来: 第一种等待.memory等待
1702 0
|
SQL Oracle 关系型数据库
一款在线ER模型设计工具,支持MySQL、SQLServer、Oracle、Postgresql sql导入
给大家介绍一款在线ER模型生成的工具,可以针对多种数据库的DDL文件在线生成ER模型图表,支持MySQL、SQLServer、Oracle、PostgreSQL等数据库。主要功能如下: 支持表的创建,同时可以根据数据库的类型不同编辑表结构、字段类型、主键、默认值、索引、备注信息等等 支持视图,触发器,sequence,存储过程,函数的查看及编辑 同步生成SQL供用户操作 访问地址: 数据库ER模型图。
4416 0