SQL Server 为什么有时候无法杀(kill)掉一个线程(spid)

有些人可能见过一种叫做non-yielding scheduler(个人解释:非让步调度器程序)的现象。在这种情况下,线程正在使用处理器,并且在使用超过线程量程(4毫秒,不可更改)后不会自动退出。有一个名为调度器监视器的后台任务,它检查SQL Server内的各种调度器上的进度,并在发现问题时发出警告。对于non-yielding Scheduler程序,你会看到错误17883,如下所示:

Process 56:0:0 (0xdee) Worker 0x041611F6 appears to be non-yielding on Scheduler 2.
Thread creation time: 13884536031127. Approx Thread CPU Used: kernel 18 ms, user 263 ms.
Process Utilization 0%. System Idle 98%. Interval: 331220558 ms.

可能发生这种情况的原因有很多,包括I/O子系统问题、对Windows API的缓慢调用或SQL Server错误。
官网解释

在SQL Server错误的情况下,这是因为线程做了一些特殊处理,它能够在不检查4ms量程是否已经过期的情况下循环(通过调用SQLOS函数YieldAndCheckForAbort,或几种变体之一)。如果线程不检查量程是否已经过期,它不会知道,因此不会让步,然后您就拥有了一个非让步调度程序。错误是缺少对 YieldAndCheckForAbort 的调用。

你可能想杀死这个线程的SPID。可以运行该命令,但它可能不会执行任何操作。这是因为没有办法在SQL Server中'强制'终止这个线程。因为线程必须检查它是否被要求终止,然后它终止自己(以及它在执行并行操作时可能创建的任何子线程)。猜猜这个检查在哪里完成?在YieldAndCheckForAbort函数中!所以如果线程缺少对 YieldAndCheckForAbort 的调用,它就不会知道,所以不会终止。

这就是为什么有时无法kill掉一些线程,最终不得不重新启动 SQL Server。

posted @   VicLW  阅读(1921)  评论(0编辑  收藏  举报
编辑推荐:
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示