SQL Server OS的任务调度机制

发表于:2013-2-17 09:49

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:CareySon    来源:51Testing软件测试网采编

分享:

  一般来说,这个值您都无需进行设置,但也有一些情况,需要设置这个值。那就是Worker线程用尽,此时除了DAC之外,您甚至无法连入SQL Server。

  Worker实际上会对应Windows上的一个线程,并与某个特定Scheduler绑定,每一个Worker只要开始执行Task,除非Task完成,否则Worker永远不会放弃这个Task,如果一个Task在运行过程由于锁、IO等陷入等待,那么实际上Worker就会陷入等待。

  此外,同一个连接内的多个Batch之间倾向于使用同一个Worker,比如第一个Batch使用了Worker 100,那么第二个Batch也同样倾向于是用Worker 100,但这并不绝对。

  正在运行的任务所是用的Worker,我们可以通过DMV sys.dm_exec_requests查看正在运行的任务,其中的Task_Address列可以看到正在运行的Task,再通过sys.dm_os_tasks的Worker_Address来查看对应的Worker。

  SQL Server会为每一个Worker保留大约2M左右的内存,对于每一个Scheduler上所能有的Worker数量是服务器的最大Worker数量/在线的Scheduler,每一个Scheduler所绑定的Worker会形成Worker池,这意味着每一个Scheduler需要Worker时,首先在Worker池中中查找空闲的Worker,如果没有空闲的Worker时,才会创建新的Worker。这个行为会和连接池类似。

  那么当一个Scheduler空闲超过15分钟,或是Windows面临内存压力时。SQL Server就会尝试Trim这个Worker池来释放被Worker所占用的内存。

  Task

  Task是Worker上运行的最小任务单元。只能拿到Worker的Task才能够运行。我们可以看下面一个简单的例子,如代码1所示。

SELECT @@VERSION
go

SELECT @@SPID
go

代码1.一个连接上的两个Batch

  代码1中的两个Batch属于一个连接,每一个Batch中都是一个简单的Task,如我们前面所说,这两个Task更倾向于复用同一个Worker,因为他们属于同一个连接。但也有可能,这两个Task使用了不同的Worker,甚至是不同的Scheduler。

  除了用户所用的Task之外,还有一些永久的系统Task,这类Task会永远占据Worker,这些Task包括死锁检测、Lazy Writer等。

  Task在Scheduler上的平均分配

  新的Task还会尝试在Scheduler之间平均分配,可以通过sys.dm_os_schedulers来看到一个load_factor列,这列的值就是用于供Task向Scheduler进行分配时,用来参考。

  每次一个新的Task进入Node时,会选择负载最少的的Scheduler。但是,如果每次都来做一次选择,那么就会在Task入队时造成瓶颈(这个瓶颈类似于TempDB SGAM页争抢)。因此SQL OS对于每一个连接,都会记住上次运行的Scheduler ID,在新的Task进入时作为提示(Hint)。但如果一个Scheduler的负载大于所有Scheduler平均值的20%,则会忽略这个提示。负载可以通过上面提到的load_factor列来看,对于某个Task运行的时间比较长,则很有可能造成Scheduler上Task分配的不均匀。

  Worker的Yield

  由于SQL Server是非抢占式调度,那么就不能为了完成某个Task,让Worker占据Scheduler一直运行。如果是这样,那么处于Runnable的Worker将会饥饿,这不利于大量并发,也违背了SQL OS调度的初衷。

  因此,在合适的时间点让出Scheduler就是关键。Worker让出CPU使得其它Worker可以运行的过程称之为yield。yield大体可分为两种,一种是所谓的“natural yield”,这种方式是Worker在运行过程中被锁或是某些资源阻塞,此时,该Worker就会让出Scheduler来让其它Worker运行。另外一种情况是Worker没有遇到阻塞,但在时间片到了之后,主动让出Scheduler,这就是所谓的“voluntarily yield”,这也就是SOS_SCHEDULER_YIELD等待类型的由来,一个Worker由RUNNING状态转到WAITING状态的过程被称之为switching。SQL OS的一个基本思想就是,要多进行switching,来保证高并发。下面我们来看几种常见的yield场景:

  ● 基于时间片的voluntarily yield大概使得Worker每4秒yield一次。这个值可以通过sys.dm_os_schedulers的quantum_length_us列看到。

  ● 每64K结果集排序,就做一次yield。

  ● 语句complie,会做yield。

43/4<1234>
精选软件测试好文,快来阅读吧~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号