谈谈SQL server的 worker threads

我们都知道SQL server的worker thread是SQL server 用来执行task的工作线程。Worker threads 的数目缺省是SQL server 动态创建的,需要多少就会创建多少,直到到达“max worker threads”的上限。如果你想改变缺省的worker threads,那么可以使用下面的脚步修改:

 

exec sp_configure'show advance',1

go

reconfigure with override

go

exec sp_configure'max worker threads',500

go

reconfigure with override

 

重新启动SQL Server 服务,然后运行,你就会发现SQL server的 max worker threads 参数已经生效:

 

exec sp_configure'max worker threads'

结果:

 

一般情况下,max worker threads的缺省值是0,表示SQL Server 就能够根据用户请求自动确定正确的活动工作线程数。这时候sp_configure 不会告诉你现在的 max worker threads的数目:

 

exec sp_configure'max worker threads'

结果:

 

你会注意到config_value 和 run_value都是0。那么如何得知SQL server 决定的那个 max worker threads是多少呢?答案就是察看DMV sys.dm_os_sys_info:

 

select max_workers_count,scheduler_count,cpu_count,hyperthread_ratio from sys.dm_os_sys_info

 

结果如下:

 

该DMV还输出一个比较有意思的column就是 hyperthread_ratio. 它表示一个物理处理器包公开的逻辑内核数与物理内核数的比,而并不能告诉您服务器是否启用了hyperthread 模式。我上面的结果表示一个物理CPU socket 包含了4个CPU。

 

让我们来谈谈一个有趣的话题。我的SQL server 的worker threads是否够用?如何判断SQL server 用光了所有的worker threads?

 

一个简单的方法就是查询DMV sys.dm_os_schedulers:

 

SELECT    scheduler_id, cpu_id, current_tasks_count, runnable_tasks_count, current_workers_count, active_workers_count, work_queue_count

FROM sys.dm_os_schedulers

WHERE scheduler_id < 255

 

结果如下:

 

其中的work_queue_count表示正在等待worker 的task数。如果这个值一直大于0,那么说明没有可用的worker threads了。这个时候如果runnable_tasks_count很大,那么一般意味着SQL Sever有某种性能瓶颈,或者是严重过载了。

另外一个DMV 也能告诉您是否有task等待worker threads:

 

select * from sys.dm_os_tasks where task_state='PENDING'

 

如果上面语句有输出,那么就表示有task 等待worker去执行。

 

在performance monitor SQL server也提供了一个类似的counter来监控worker的使用情况。SQL Server Wait Statistics 对象里面的Wait for the worker 表示等待工作线程的统计信息,截图如下:

 

 

还有一个可能您会搞错的概念就是, 是否一个connection 对应一个worker thread? 答案当然是NO。 一个connection 会提交batch,这个batch变成一个或多个task,然后这些task由 某个(多个)worker thread执行。执行完毕后这些worker threads又会执行属于其他connection 的task,直到没有task执行。所以,理论上,200多个worker threads可以服务上千上万的 connections.