如何解决 SQL Server 中的最大工作线程问题
在我们讨论相关的性能问题之前最大工作线程数(MWT),让我们了解一下随钻测量做。随钻测量是可用于 SQL Server 的工作线程,并且使用本机 Windows 线程 SQL Server 同时并行处理多个任务。例如,数据库检查点、网络层进程、处理事务处理等。默认值为 0。0 值允许 SQL Server 根据服务器资源动态生成线程。它适用于全球大多数 SQL Server 部署。为了提高性能,有时手动增加 MWT 值会有所帮助。在这篇文章中,我将讨论如何解决 SQL Server 中的最大工作线程问题。
仅当 SQL Server 非常繁忙、用户并发性较高且启用了 SQL Server Always On、复制服务等附加功能时,您才会用完 MWT。根据 SQL Server 版本(32 位或 64 位)和处理器核心,SQL Server 生成工作线程池来服务用户请求。以下是硬数据的快速浏览。
了解更多:2019 年如何在 Azure 存储上进行 SQL Server 混合备份到 URL
| CPU 核心数 | 较旧的 32 位服务器 | 最新 64 位服务器 |
|---|---|---|
| 最多 4 个处理器 | 256 | 第512章 |
| 八核 8 处理器 | 288 | 第576章 |
| 16 个处理器 | 第352章 | 704 |
| 32 个处理器 | 第480章 | 960 |
| 64 个处理器 | 第736章 | 第1472章 |
| 128 个处理器 | 4224 | 4480 |
| 256 个处理器 | 8320 | 8576 |
MWT 配置选项不包括用于 Always On 可用性组和数据库镜像的线程。
使用以下查询找出哪些系统任务导致产生额外的工作线程:
SELECT
s.session_id,
r.command,
r.status,
r.wait_type,
r.scheduler_id,
w.worker_address,
w.is_preemptive,
w.state,
t.task_state,
t.session_id,
t.exec_context_id,
t.request_id
FROM sys.dm_exec_sessions AS s
INNER JOIN sys.dm_exec_requests AS r
ON s.session_id = r.session_id
INNER JOIN sys.dm_os_tasks AS t
ON r.task_address = t.task_address
INNER JOIN sys.dm_os_workers AS w
ON t.worker_address = w.worker_address
WHERE s.is_user_process = 0;
如何使用 T-SQL 更改最大工作线程数
USE AdventureWorks2016 ; GO EXEC sp_configure 'show advanced options', 1; GO RECONFIGURE ; GO EXEC sp_configure 'max worker threads', 1000 ; GO RECONFIGURE; GO
有时,减少工作线程数可以提高性能
数据库镜像和 Always On 可用性组的最大工作线程最佳实践
- 为了避免 MWT 耗尽,请不要创建超过 10 个可用性组和 100 个数据库。这意味着每个可用性组有 10 个 DB。这是建议,而不是硬性限制。
- 如果 MWT 耗尽,请添加其他 CPU 或虚拟 CPU(如果是虚拟机)以增加 MWT 计数。请参阅上表以供参考。
- 在同一服务器上创建另一个实例来改进 MWT 不会提高性能。
- 运行镜像和可用性组的数据库进行过多的数据库整合可能会导致 MWT 耗尽。
- 始终在 AG 上实施之前计算最大 MWT 并广泛测试系统。
如何计算 MWT 计数?
MWT = {512 + ((Number of CPU Cores - 4) * 16)} = Result
如何计算最大工作线程使用率
select scheduler_id,current_tasks_count, current_workers_count,active_workers_count,work_queue_count from sys.dm_os_schedulers where status = ‘Visible Online’
哪个系统任务正在使用 MWT 线程的详细信息
select is_preemptive,state,last_wait_type,count(*) as NumWorkers from sys.dm_os_workers Group by state,last_wait_type,is_preemptive order by count(*) desc
