CPU 核心和 sys.dm_os_workers

Jam*_*ell 3 sql-server availability-groups sql-server-2017

我们最近将 AOAG 集群故障转移到了次要区域。在第一个区域,我们的盒子有 32 个核心,而在第二个区域,我们有 64 个核心。流量相似,但是在较大的机器上,我们在 sys.dm_os_workers 中运行更多数量的工作线程(以及 sys.dm_os_threads 中的线程)。这是提高 CPU 核心时的预期行为吗?还是我们应该担心所有这些闲置的工作人员?

我们正在运行 SQL Server 2017 CU 24。

max worker threads配置为0(默认值)。

max degree of parallelism在两个区域都配置为2

在当前服务器中,我们看到以下计数:

会话计数 请求数 工人数量 线程数
2366 第389章 第1172章 1265

Sea*_*ser 7

我真正想回答的是,当我们增加 CPU 数量时,工作人员数量是否应该大幅增加?

流量相似,但是在较大的机器上,我们在 sys.dm_os_workers 中运行更多数量的工作线程(以及 sys.dm_os_threads 中的线程)。

在不讨论细节的情况下,对于正常负载下的服务器来说,核心数量对进程中的工作线程或线程数量几乎没有影响。

线程的使用分为三个不同的类别,第一个是以抢占模式运行长期永久任务所需的线程,例如 AG 设置中的租用、CLR 托管等,或第 3 方模块项(例如驱动程序)提供商。第二个桶是与 SQL 相关的长期永久任务,例如调度程序管理器、lazywriter 和其他 SQL 引导项目,这些项目往往按numa 节点而不是按核心数量进行分区。第三个桶是与 SQL 查询执行相关的项目,例如满足查询或登录。

除了第一个之外,工作人员属于相同的类别,因为没有与这些类型的线程关联的工作人员构造(下面的示例)。

虽然由于前两个存储桶假设有更多 numa 节点,您将拥有更多线程和工作人员,但除非线程和工作人员数量已经很低,否则情况应该不会太严重。主要区别在于工作分配的地点。由于每个调度程序都有一定的本地队列,并且工作分布在更多的调度程序中,因此将会有更多的工作线程和线程,因为即使有一个额外的调度程序也将需要多一个线程和工作线程。

正常的服务器活动将根据需要启动和关闭工作线程和线程。工作量的周期性峰值或日程安排的变化可能会使这种影响看起来比预期的要大,但这是正常的。

不过,总的来说,除非您达到最大工作线程数,否则无需担心 - 在这种情况下,将值更改为其他值将不是作为解决方案的适当操作过程。

示例 - 存储桶 1:长期非 SQL 永久

sqlservr!DCOMInitThread
kernel32!BaseThreadInitThunk
ntdll!RtlUserThreadStart
Run Code Online (Sandbox Code Playgroud)

示例 - 存储桶 2:长期运行的 SQL Bootstrapped

sqlmin!lazywriter
sqldk!SOS_Task::Param::Execute
sqldk!SOS_Scheduler::RunTask
sqldk!SOS_Scheduler::ProcessTasks
sqldk!SchedulerManager::WorkerEntryPoint
sqldk!SystemThread::RunWorker
sqldk!SystemThreadDispatcher::ProcessWorker
sqldk!SchedulerManager::ThreadEntryPoint
kernel32!BaseThreadInitThunk
ntdll!RtlUserThreadStart
Run Code Online (Sandbox Code Playgroud)

示例 - 存储桶 3:常规 SQL 用户工作负载

sqllang!CXStmtSelect::XretExecute
sqllang!CExecStmtLoopVars::ExecuteXStmtAndSetXretReturn
sqllang!CMsqlExecContext::ExecuteStmts<1,0>
sqllang!CMsqlExecContext::FExecute
sqllang!CSQLSource::Execute
sqllang!process_request
sqllang!process_commands_internal
sqllang!process_messages
sqldk!SOS_Task::Param::Execute
sqldk!SOS_Scheduler::RunTask
sqldk!SOS_Scheduler::ProcessTasks
sqldk!SchedulerManager::WorkerEntryPoint
sqldk!SystemThread::RunWorker
sqldk!SystemThreadDispatcher::ProcessWorker
sqldk!SchedulerManager::ThreadEntryPoint
kernel32!BaseThreadInitThunk
ntdll!RtlUserThreadStart
Run Code Online (Sandbox Code Playgroud)


Han*_*non 5

threadpool由于会话数超过 2300 个,服务器在之前的区域中运行时很可能会遇到大量等待。

默认情况下,SQL Server 根据可用核心数配置最大工作线程数。有关详细信息,请参阅文档,但只要说这些是 SQL Server 2017 的默认值就足够了:

CPU数量 64 位计算机(从 SQL Server 2016 (13.x) SP2 和 SQL Server 2017 (14.x) 开始)
<= 4 第512章
8 第576章
16 704
32 960
64 第1472章
128 4480
256 8576

正如您所看到的,从 32 核增加到 64 核会将最大工作线程数从 960 增加到 1472。根据服务器的实际繁忙程度,您可能希望将线程数从默认值增加。查看Erik Darling 的 sp_PressureDetector 过程,了解有关线程发生情况的详细信息。