Troubleshooting SQL Server RESOURCE_SEMAPHORE Waittype Memory Issues
前言: 本文是对博客https://www.mssqltips.com/sqlservertip/2827/troubleshooting-sql-server-resourcesemaphore-waittype-memory-issues/的翻译,本文基本直译,部分地方读起来有点不自然。 如有翻译不对或不好的地方,敬请指出,大家一起学习进步。尊重原创和翻译劳动成果,转载时请注明出处http://www.cnblogs.com/kerrycode/p/7068246.html。谢谢!
问题描述
今天,我们的一个SQL Server实例性能变得非常慢。当我登录到数据库服务器进行一些初始检查时,我最初始观察、注意到的是它的内存压力(memory pressure)。接下来,我们必须找出是什么导致我们的实例出现内存紧张。当我检查事务的等待类型时,RESOURCE_SEMAPHORE等待是大多数事务的问题。在这篇文章中,我将描述这个问题,以及如何查找哪个查询语句或事务导致了内存压力
解决方案
当我检查所有事务的等待类型时,大多数事务的等待类型为RESOURCE_SEMAPHORE 等待以及某些页面IO等待。页面IO等待也是由于内存压力导致,因为这些事务无法获得足够的内存来执行这个操作。
资源信号量等待
在继续之前,我想对资源信号量(Resource_semaphore)等待进行一些说明,以便您可以更好地了解SQL Server是如何将内存授予SQL Server查询语句的。
当SQL Server收到用户发送的查询请求(查询语句)时,它首先创建一个编译过的计划,然后在这个基础上创建一个执行步骤(个人觉得执行步骤比执行计划要合适)。当SQL Server创建一个编译过的计划时,它会计算两个内存授予参数,称为“请求内存”(required memory)和“附加内存”(additional memory)。请求内存是运行排序和HASH连接所需的最小内存。它之所以是 "必需"的, 是因为如果没有可用的“请求内存”, 查询将无法启动。附加内存(additional memory)是在内存中存储临时行(个人觉得翻译为中间结果可能更合理)所需的内存量。这被称为额外(附加)的,因为如果没有足够可用的“附加内存”可以将查询的中间结果存储在磁盘上。
首先,服务器计算任何给定的查询执行需要多少内存。这通常是“请求内存”(required memory)和“附加内存”(additional memory)的总和,但如果您的实例正在并行处理,那么所需的内存将是(所需的内存* DOP)+附加内存。服务器检查所需的内存是否超过每个查询限制,然后服务器减少“附加内存”,直到总数达到限制。这个修改后的大小称为请求内存。SQL Server有一个内部工具称为资源信号量(RESOURCE SEMAPHORE),用于将此请求的内存授予查询。如果无法通过资源信号量向该请求的内存授予查询,那么如果查询sys.sysprocesses系统表或sys.dm_exec_request DMV,则该查询将处于等待状态,并出现RESOURCE_SEMAPHORE等待类型。
当资源信号量(Resource_semaphore)接收到新的请求时,它首先检查是否有任何查询正在等待中。只要发现存在即是一个等待查询,那么会将新查询(新请求)放入队列中,因为等待队列是以先到先得的方式设计的,并且有小权重以支持于小型查询。当没有等待查询或查询返回保留的内存时。资源信号量尝试授予内存。如果找到足够的内存,那么请求内存被授予并且查询可以开始运行,并且如果没有找到足够的可用内存来授予所请求的内存,那么它将当前查询放入等待队列中,并且给当前会话RESOURCE_SEMAPHORE等待类型, 此时服务器开始面临内存压力。
识别RESOURCE_SEMAPHORE等待
步骤1
首先,我们需要研究我们的实例,弄清楚为什么在SQL Server中出现内存压力。要查看所有事务的大概信息,我们可以查询sys.sysprocesses,或者我们可以使用sys.dm_exec_requests DMV。
SELECT ),另一个表示小型查询(resource_semaphore_id为1),小于5 MB。在这里,您可以获得实例的总授予内存和总可用内存。请参阅grantee_count和waiter_count上的数字,grantee_count是已经分配了内存的总查询数,waiter_count是队列中等待获取内存的总查询数量。所以在这里我们可以看到大约100个查询正在等待获得他们要求的内存。
SELECT * FROM sys.dm_exec_query_resource_semaphores

步骤3
现在我们将获取所有正在等待队列中获取所请求的内存的所有查询的详细信息,我们将使用DMV sys.dm_exec_query_memory_grants来获取队列中等待分配内存的查询总数。对于等待获取其请求的内存的查询,grant_time和granted_memory_kb列将为NULL。您可以在下面的截图中查看所请求的内存量及其等待状态,因为它们的grant_time和granted_memory_kb值为NULL。我们还可以使用该DMV获取所有查询的plan_handle和sql_handle。稍后我们将使用这些值来获取确切的查询。
注意:有太多列要显示,可以只显示部分所需的列。
SELECT * FROM sys.dm_exec_query_memory_grants

步骤4
现在,我们将找到内存密集型查询。我们可以看到所有等待查询的请求内存。在这里我们可以看到所请求的内存对于大多数事务来说太大了。我们将获得所有这些查询的plan_handle,以获得确切的SQL文本来查看查询计划。
从sys.dm_exec_query_memory_grants中选择前10个*
select top 10 * from sys.dm_exec_query_memory_grants

步骤5
现在我们将使用上面查询所获得的plan_handle和sql句柄来获取SQL代码。
运行以下语句从上述查询中获取SQL代码,使用sql_handle。
SELECT * FROM sys.dm_exec_sql_text(sql_handle)

我们还可以使用步骤4中查询中的plan_handle获取SQL计划。
SELECT * FROM sys.dm_exec_sql_plan(plan_handle) --译者注 实际没有sys.dm_exec_sql_plan, 而是sys.dm_exec_query_plan,估计是作者笔误。
结论
现在我们已经找到内存密集型查询及其执行计划,我们的下一步是研究这些查询,并找出如何调整、优化它们。我们应该查看查询中是否使用的错误的索引或是否存在索引缺失的情况,并创建正确的索引。在我们这种情况下,这是由于糟糕的索引设计导致了内存紧张。在创建、调整合适的索引之后,相同的查询运行的时候请求的内存就会少得多。
下一步
- 使用此提示来识别由于内存不足而消耗更多内存并将剩余的事务置于等待状态的查询。
- 还要查看上述DMV的其他列,并将它们联系起来,以便更好地分析和了解性能问题。
- 这些DMV应提供大量信息,以便您能够识别问题。
- 阅读有关性能调优的更多提示,以提高系统性能。
Troubleshooting SQL Server RESOURCE_SEMAPHORE Waittype Memory Issues的更多相关文章
- SQL Server 内存泄露(memory leak)——游标导致的内存问题
原文:SQL Server 内存泄露(memory leak)--游标导致的内存问题 转自:http://blogs.msdn.com/b/apgcdsd/archive/2011/07/01/sql ...
- 《Troubleshooting SQL Server》读书笔记-CPU使用率过高(下)
<Troubleshooting SQL Server>读书笔记-CPU使用率过高(下) 第三章 High CPU Utilization. CPU使用率过高的常见原因 查询优化器会尽量从 ...
- 《Troubleshooting SQL Server》读书笔记-内存管理
自调整的数据库引擎(Self-tuning Database Engine) 长期以来,微软都致力于自调整(Self-Tuning)的SQL Server数据库引擎,用以降低产品的总拥有成本.从SQL ...
- 將sql server 2008R2 Max memory 意外設為0
做sql server 內存Max memory 設定時大意,誤把最大值設為0,怎麼著都連不上DataBase,哪真叫個急呀,最後還是看到一條文命令把救回來了,其它很簡單急的時候就是沒想出來. 1.暫 ...
- 《Troubleshooting SQL Server》读书笔记-CPU使用率过高(上)
第三章 High CPU Utilization. CPU使用率过高问题很容易被发现,但是诊断却不是很容易.CPU使用过高很多时候会成为其它问题的替罪羊,所以在确认和故障诊断时要抽丝剥茧. 调查CPU ...
- 高老大 ‘SQL Server 优化器特性导致的内存授予相关BUG’ 学习笔记
今天高老大出了好文章.在这里 自己本来对这一块比较混乱,正好借这个机会学习一下. 就用高老大的脚本.需要的直接去他那里找吧,这里就省了. 加查询优化标记前后对比 可以看到GrantedMemory是5 ...
- Memory Manager surface area changes in SQL Server 2012
here were various changes to memory related DMVs, DBCC memory status, and Perfmon counters in SQL Se ...
- 非常全面的SQL Server巡检脚本来自sqlskills团队的Glenn Berry 大牛
非常全面的SQL Server巡检脚本来自sqlskills团队的Glenn Berry 大牛 Glenn Berry 大牛会对这个脚本持续更新 -- SQL Server 2012 Diagnost ...
- SQL Server 内存相关博文
Don’t confuse error 823 and error 832 本文大意: 错误832: A page that should have been const ...
随机推荐
- 函数式编程之-Currying
这个系列涉及到了F#这门语言,也许有的人觉得这样的语言遥不可及,的确我几乎花了2-3年的时间去了解他:也许有人觉得学习这样的冷门语言没有必要,我也赞同,那么我为什么要花时间去学习呢?作为一门在Tiob ...
- 手把手在Ubuntu上面安装Docker
一.环境准备 1.Ubuntu64位系统(目前docker仅支持64位系统) 2.官方支持的Ubuntu版本(1)Ubuntu Trusty 14.04(LTS)(2)Ubuntu Precise 1 ...
- react入门学习及总结
前言 不知不觉一年又过去了,新的一年又到来,2019应该要好好思考,好好学点有用的东西,规划下自己今后的学习方向,不要再像以前那样感觉很迷茫. react简单介绍 官网及中文文档 https://re ...
- http无状态协议,cookie和session详解(一)
1.HTTP无状态协议 首先看百度百科给出的定义: HTTP无状态协议,是指协议对于事务处理没有记忆能力.缺少状态意味着如果后续处理需要前面的信息,则它必须重传, 这样导致可能每次连接传送的数据量增大 ...
- 了解golang的可变参数(... parameters),这一篇就够了
在实际开发中,总有一些函数的参数个数是在编码过程中无法确定的,比如我们最常用的fmt.Printf和fmt.Println: fmt.Printf("一共有%v行%v列\n", r ...
- [android] 插入一条记录到系统短信应用里
谷歌市场上有这些应用,模拟短信,原理就是把数据插入到短信应用的数据库里 获取ContentResolver对象,通过getContentResolver()方法 调用resolver对象的insert ...
- curl模拟ip和来源进行网站采集的实现方法
对于限制了ip和来源的网站,使用正常的采集方式是不行的.这里说我的一种方法吧,使用php的curl类实现模拟ip和来源,可以实现采集限制ip和来源的网站. 1.设置页面限制ip和来源访问比如服务端的s ...
- python学习笔记(四)、条件、循环及其他语句
1 再谈print和import 1.1 打印多个参数 print 能够同时打印多个表达式,并且能自定义分隔符.如下: print('a','b','c') ——> a b c print('a ...
- springMVC_08文件上传
一.步骤总结 导入jar包 配置web.xml 在src目录下创建配置文件mvc.xml 创建前段页面fileupload.jsp 创建controller类HelloController 配置mvc ...
- Android开发过程中的坑及解决方法收录(一)
之前使用了Android Studio的插件直接为button绑定了监听器,并实现onClick方法(我的onClick方法无论点击哪一个都是要实现setcontentview这个方法设置layout ...