谈谈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.