SQL Server邮件相关SQL语句出现严重的ASYNC_NETWORK_IO等待事件案例
DPA监控发现一台SQL Server服务器最近两天执行系统存储过程msdb.dbo.sp_MailItemResultSets中的某个SQL时,出现较严重的ASYNC_NETWORK_IO等待。如下截图所示
进一步分析发现,主要是执行存储过程msdb.dbo.sp_MailItemResultSets中下面这段SQL语句出现ASYNC_NETWORK_IO等待
SELECT
mi.mailitem_id,
mi.profile_id,
(SELECT name FROM msdb.dbo.sysmail_profile p WHERE p.profile_id = mi.profile_id) as 'profile_name',
mi.recipients,
mi.copy_recipients,
mi.blind_copy_recipients,
mi.subject,
mi.body,
mi.body_format,
mi.importance,
mi.sensitivity,
ISNULL(sr.send_attempts, 0) as retry_attempt,
ISNULL(mi.from_address, '') as from_address,
ISNULL(mi.reply_to, '') as reply_to
FROM sysmail_mailitems as mi
LEFT JOIN sysmail_send_retries as sr
ON sr.mailitem_id = mi.mailitem_id
WHERE mi.mailitem_id = @mailitem_id
进一步分析,发现随便一个与表sysmail_allitems有关的SQL都会出现严重的ASYNC_NETWORK_IO等待:
SELECT * FROM msdb.dbo.sysmail_allitems WITH(NOLOCK)
WHERE sent_status != 'sent'
ORDER BY sent_date DESC;
另外,分析过程中发现sysmail_mailitems表只有7万多条记录,但是表的Size大小接近10G大小,如下截图所示:
这显然明显不正常,sysmail_mailitems中肯定有一些超大的邮件记录,因为这个系统经常有通过SQL,生成一些报表数据发送给用户。于是我想检查一下是否真的有一些超大的邮件。这里就必须查看sysmail_mailitems表的行大小,于是用下面脚本查看表sysmail_mailitems中行记录的大小。
USE msdb;
GO
IF object_id('sp_GetRowSize') is not null
drop procedure sp_GetRowSize
GO
CREATE procedure sp_GetRowSize(@Tablename varchar(100),@pkcol varchar(100))
AS
BEGIN
declare @dynamicsql varchar(MAX)
-- A @pkcol can be used to identify max/min length row
set @dynamicsql = 'select ' + @PkCol +' , (0'
-- traverse each record and calculate the datalength
select @dynamicsql = @dynamicsql + ' + isnull(datalength(' + name + '), 1)'
from syscolumns where id = object_id(@Tablename)
set @dynamicsql = @dynamicsql + ') as rowsize from ' + @Tablename + ' order by 2 desc'
print (@dynamicsql)
END
如下截图所示,还真的有一些邮件记录的rowsize超级大,正常情况下,rowsize只有1122个字节左右大小,而mailitem_id=5146768 这条记录居然有1352285196字节,如果换算成大小的话SELECT 1352285196.0/1024/1024
~=1290M, 真是无语了!!
原因倒也不复杂,就是生成邮件的SQL出现逻辑错误,导致邮件的Body变得无比巨大,导致msdb.dbo.sysmail_allitems变得非常大,与之相关的SQL语句IO性能变差,出现ASYNC_NETWORK_IO等待。其实以前也遇到过类似案例,请见SQL Server 2008 R2执行存储过程sp_MailItemResultSets引起大量PREEMPTIVE_OS_WAITFORSINGLEOBJEC等待,只是当时没有继续深挖Root Cause而已!
解决方案
那么如何解决这个问题呢? 很简单,就是删除表msdb.dbo.sysmail_allitems中的记录,让其Size变小。也可以删除那些mail_id非常大的记录。可以用下面脚本处理
/******************************************************************************************************
Script Function : 以下示例按条件删除数据库邮件系统中的电子邮件
*******************************************************************************************************/
DECLARE @GETDATE datetime
SET @GETDATE = GETDATE()-2;
EXECUTE msdb.dbo.sysmail_delete_mailitems_sp @sent_before = @GETDATE;
GO
其实sysmail_delete_mailitems_sp中的逻辑也是去删除msdb.dbo.sysmail_allitems 中的记录,如下所示,在处理的过程中,需要在业务空闲的时候处理,否则会引起大量阻塞。
DELETE
FROM msdb.dbo.sysmail_allitems
WHERE ((@sent_before IS NULL)
OR ( send_request_date < @sent_before))
AND ((@sent_status IS NULL)
OR (sent_status = @sent_status))
CREATE PROCEDURE
sysmail_delete_mailitems_sp
@sent_before DATETIME = NULL, -- sent before
@sent_status varchar(8) = NULL -- sent status
AS
BEGIN
SET @sent_status = LTRIM(RTRIM(@sent_status))
IF @sent_status = ''
SET @sent_status = NULL
IF ( (@sent_status IS NOT NULL) AND
(LOWER(@sent_status collate SQL_Latin1_General_CP1_CS_AS) NOT IN ( 'unsent', 'sent', 'failed'
, 'retrying') ) )
BEGIN
RAISERROR(14266, -1, -1, '@sent_status', 'unsent, sent, failed, retrying')
RETURN(1) -- Failure
END
IF ( @sent_before IS NULL AND @sent_status IS NULL )
BEGIN
RAISERROR(14608, -1, -1, '@sent_before', '@sent_status')
RETURN(1) -- Failure
END
/* BEGIN ACTIVE SECTION (comment inserted by DPA) */
DELETE
FROM msdb.dbo.sysmail_allitems
WHERE ((@sent_before IS NULL)
OR ( send_request_date < @sent_before))
AND ((@sent_status IS NULL)
OR (sent_status = @sent_status))
/* END ACTIVE SECTION (comment inserted by DPA) */
DECLARE @localmessage nvarchar(255)
SET @localmessage = FORMATMESSAGE(14665, SUSER_SNAME(), @@ROWCOUNT) exec
msdb.dbo.sysmail_logmailevent_sp @event_type=1,
@description=@localmessage
END
SQL Server邮件相关SQL语句出现严重的ASYNC_NETWORK_IO等待事件案例的更多相关文章
- SQL SERVER如何通过SQL语句获服务器硬件和系统信息
在SQL SERVER中如何通过SQL语句获取服务器硬件和系统信息呢?下面介绍一下如何通过SQL语句获取处理器(CPU).内存(Memory).磁盘(Disk)以及操作系统相关信息.如有不足和遗漏,敬 ...
- PowerDesigner反向数据库时遇到[Microsoft][ODBC SQL Server Driver][SQL Server]无法预定义语句。SQLSTATE = 37错误解决方法
逆向工程中,有时会出现如下错误 ... [Microsoft][ODBC SQL Server Driver][SQL Server]无法预定义语句 SQLSTATE = 37000 解决方案: 1. ...
- SQL SERVER 复制相关存储过程
适用于所有类型复制的过程 过程 说明 sp_addscriptexec 向发布的所有订阅服务器发布 Microsoft SQL Server 脚本(.sql 文件). sp_adjustpublish ...
- SQL Server Profiler监控执行语句
SQL Server Profiler监控执行语句,这个功能主要用在实时的监控对数据库执行了什么操作,从而及时有效的跟踪系统的运行. 常规配置选项,名称.模板.保存到文件(可以复用). 事件选择,可以 ...
- SQL Server 日期相关
原文:SQL Server 日期相关 原帖出处:http://blog.csdn.net/dba_huangzj/article/details/7657979 对于开发人员来说,日期处理或许简单,或 ...
- SQL Server 定时执行SQL语句的方法
SQL SERVER 定时任务,你可以启动一下.不过要想更加直观的控制,直接写一个程序,定时执行你的存储过程. 1.设置“SQL Server 代理”(SQL Server Agent)服务随系统启动 ...
- SQL Server FOR XML PATH 语句的应用---列转行
经常在论坛看到高手使用了 for xml path,由于是搜索一下,记录了详细的使用方法.在SQL Server中利用 FOR XML PATH 语句能够把查询的数据生成XML数据,下面是它的一些应用 ...
- SQL Server中的流控制语句
begin···end 该语句定义sql代码块,通常在if和while语句中使用 declare @num int ; ; begin ; print 'hello word' end if···el ...
- SQL SERVER: 合并相关操作(Union,Except,Intersect)
SQL SERVER: 合并相关操作(Union,Except,Intersect) use tempdb create table tempTable1 (id int primary key id ...
随机推荐
- Dubbo源码学习之-通过源码看看dubbo对netty的使用
前言 前段时间,从头开始将netty源码了解了个大概,但都是原理上理解.刚好博主对dubbo框架了解过一些,这次就以dubbo框架为例,详细看看dubbo这种出色的开源框架是如何使用netty的,又是 ...
- Rethinking the performance comparison between SNNS and ANNS
郑重声明:原文参见标题,如有侵权,请联系作者,将会撤销发布! Abstract ANN是通向AI的一种流行方法,它已经通过成熟的模型,各种基准,开源数据集和强大的计算平台获得了非凡的成功.SNN是一类 ...
- Python最火的第三方开源测试框架 ——pytest
一.介绍 本篇文章是介绍的是Python 世界中最火的第三方单元测试框架:pytest.它有如下主要特性: assert 断言失败时输出详细信息(再也不用去记忆 self.assert* 名称了) 自 ...
- 力扣Leetcode 面试题51. 数组中的逆序对 - 归并排序
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数. 示例 1: 输入: [7,5,6,4] 输出: 5 限制: 0 <= ...
- Android开发之ScrollView去掉右侧滚动条,gridview如何去掉外边框
android:scrollbars="none" android:listSelector="@null"
- 如何写好转正答辩PPT
如何写好一个转正答辩报告 几个月前,我刚经历了转正答辩,这是我职业生涯中转正答辩表现最好的一次.在我之前经历的几家公司中,转正的流程各不相同,我将它们为主动式和被动式.这里的被动式指的是:公司是主动方 ...
- C++11的decltype关键字
C++11的decltype关键字 概述 decltype关键字和auto有异曲同工之处 有时我们希望从表达式的类型推断出要定义的变量类型,但是不想用该表达式的值初始化变量(如果要初始化就用auto了 ...
- Leetcode 974 和可被K整除的子数组
题目: 解法 //前缀和算法+hash表 class Solution { public: int subarraysDivByK(vector<int>& A, int K) { ...
- 我的T440p出现怪事情了
装上系统后,再稍微装些软件,或是打补丁,升级驱动什么的,再重启就起不来了. 也就是说,装一次系统只能好一次,关机或是重启就启动不了了,现象是在黑屏界面转两下就转不动了. 鼓捣一个周末也无效,昨天上系统 ...
- JavaScript五中迭代方法小解
ECMAScript 为数组定义了五个迭代方法.每个方法都接收两个参数:要在每一项上运行的函数和(可选的)运行该函数的作用域对象——影响this的值.传入这些方法中的函数会接收三个参数:数组项的值.该 ...