这部分会在第7章中详细介绍。当一个应用程序(包括SSMS)成功与SQL Server建立联系之后,会有一个会话ID(session_id)与这个连接相关联,可以通过查询sys.dm_exec_sessions这个DMV来获取当前所有已授权的会话列表。当一个会话发出一个请求时,SQL Server会把这个请求拆分一个或多个任务(tasks),然后关联对应个数的工作者线程(worker thread),每个线程都会有如下3个状态。
1)running。一个处理器在某个时刻只能做一件事情,当一个线程正在一个处理器上运行时,这个线程的状态就为running。
2)suspended。如果在SQL Server的一个线程中进行协同操作的调度(Scheduler,后面提到)需要运行起来,而此时SQL Server没有足够的资源,那么线程会放弃当前占有的处理器,变成挂起(suspended)状态,等待这个协同操作运行结束。这种状态在SQL Server中也叫等待(wait)。
3)runnable。如果一个线程已经完成等待,但是还没有轮到它运行,就会变成runnable状态,代表已经准备好被执行。这种叫信号等待(signal wait)。
如果当前SQL Server已经没有可用的工作者线程,并且最大工作线程数还没达到,那么会分配一个新的工作线程。如果最大线程已经达到,那么这个任务会变成等待状态,这个等待类型叫作threadpool,直到有可用的线程为止。默认的最大线程数是基于CPU体系和逻辑核心数的(这在第2章已经介绍过)。下面是逻辑CPU格式在不同位数的操作系统中能支持的最大工作者线程数。
1)对于32位操作系统:
总可用逻辑CPU<=4时,最大工作者线程=256。
总可用逻辑CPU>4时,最大工作者线程=256+((逻辑CPU-4)×8)。
2)对于64位操作系统:
总可用逻辑CPU<=4时,最大工作者线程=512。
总可用逻辑CPU>4时,最大工作者线程=512+((逻辑CPU-4)×16)。
还有一个比较简单的方法可用于检查当前系统的最大线程数。比如执行下面的脚本:
SELECT max_workers_count
FROM sys.dm_os_sys_info
通常出现threadpool类型的等待意味着当前有大量并行执行计划,或者遇到了CPU瓶颈,但是不管是什么情况,都需要经常检查这部分的数据,以确保有足够的线程可用。对于每个工作线程,在64位系统中都要消耗2MB的内存,在32位系统需要消耗0.5MB的内存,所以SQL Server只会在需要的时候才创建工作线程。这部分的信息可以通过sys.dm_os_workers这个DMV来查看。
SELECT COUNT(*)
FROM sys.dm_os_workers
调度在SQL Server中显示为Scheduler。每个线程会与一个调度关联,SQL Server上可用的调度数量等于SQL Server上可用的逻辑CPU数量加上一个额外的专用管理员连接(DAC)。这部分的信息可以从sys.dm_os_schedulers这个DMV中查询。会话、任务、线程、调度和逻辑CPU之间的关系如图3-7所示。
由于Windows需要支持多种甚至所有应用软件,所以不会对上面的应用做出什么优先级排名,而SQL Server本质上和Office甚至画图软件一样,都只是Windows上的一个应用,所以SQL Server不会有多大的特权。因此SQL Server在协同操作过程中可能会被暴力地剥夺处理权,形成等待状态,这部分在第7章详细介绍。