热门标签 | HotTags
当前位置:  开发笔记 > 数据库 > 正文

5.SQLServer数据库性能监控-当前请求

对于在线运行的系统,当前数据库性能监控,通常监视以下几点:(1)是否有阻塞(Blocking);(2)是否有等待(Waiting),阻塞就是锁(Lock)等待;(3)是否运行时间过长(Longrunning);(4)是否有死锁(Deadlock);sys.dm_exec_query_stats之类,等一些统

对于在线运行的系统,当前数据库性能监控,通常监视以下几点: (1) 是否有阻塞 (Blocking); (2) 是否有等待 (Waiting),阻塞就是锁 (Lock) 等待; (3) 是否运行时间过长(Long running); (4) 是否有死锁 (Deadlock); sys.dm_exec_query_stats之类,等一些统

对于在线运行的系统,当前数据库性能监控,通常监视以下几点:

(1) 是否有阻塞 (Blocking);

(2) 是否有等待 (Waiting),阻塞就是锁 (Lock) 等待;

(3) 是否运行时间过长(Long running);

(4) 是否有死锁 (Deadlock);

sys.dm_exec_query_stats之类,等一些统计性的信息,通常不作为实时告警内容,而是在性能优化时,作为参考。

. 阻塞/等待/长时间运行

1. SQL Server 2005 及以后版本检查

SELECT r.session_id
      ,r.blocking_session_id
      ,DB_Name(r.database_id) as database_name
      ,r.start_time
      ,r.total_elapsed_time
      ,r.[status]
      ,CASE WHEN r.blocking_session_id<> 0 THEN'Blocking'
           WHEN r.blocking_session_id= 0 AND r.wait_type is not null THEN 'Waiting'
           ELSE 'Long-running'
       END as slowness_type
      ,r.percent_complete
      ,r.command
      ,r.wait_type
      ,r.wait_time
      ,r.wait_resource
      ,r.last_wait_type
      ,r.cpu_time
      ,r.reads
      ,r.writes
      ,r.logical_reads
      ,t.[text] as executing_batch
      ,SUBSTRING(t.[text],
                r.statement_start_offset/2,
                (CASE WHENr.statement_end_offset =-1 
                      THENDATALENGTH(t.[text]) --LEN(CONVERT(NVARCHAR(MAX),t.text)) * 2
               ELSE r.statement_end_offset
               END - r.statement_start_offset )/2+ 1) as executing_sql
      ,bt.[text] as blocking_batch
      ,SUBSTRING(bt.[text],
                br.statement_start_offset/2,
                (CASE WHENbr.statement_end_offset = -1 
                      THENDATALENGTH(bt.[text]) --LEN(CONVERT(NVARCHAR(MAX),bt.text)) * 2
               ELSE br.statement_end_offset
               END - br.statement_start_offset )/2+ 1) as blocking_sql
     --,p.query_plan
  FROM sys.dm_exec_requests r
 CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) as t
 CROSS APPLY sys.dm_exec_query_plan(r.plan_handle) as p
  LEFT JOIN sys.dm_exec_requests br
    ON r.blocking_session_id =br.session_id
 OUTER APPLY sys.dm_exec_sql_text(br.session_id) as bt
 WHERE r.session_id > 50 and r.session_id <> @@SPID
   AND r.total_elapsed_time >30 * 60 * 1000
 ORDER BY r.total_elapsed_timeDESC;

以上脚本返回运行超过30分钟的语句,需要注意的是:

(1) 如果返回执行计划,会让以上脚本变慢很多,可以不返回,在收到告警后检查语句时,再去查看执行计划;

(2) 显示TEXT,比如: xp_cmdshell这样的语句,start_offset, end_offset都为0,截取的 text是空白,只有看TEXT才知道是什么语句;还有就是有时需要知道这个请求来自哪个batch或者存储过程;

(3) 有时显示TEXT还不够,还以xp_cmdshell为例,需要dbcc inputbuffer才能看到完整的sql语句;另外已运行结束但还没有commit/rollback的事务,在requests中已经没有了,也需要借用dbcc inputbuffer来查看sql 语句;

dbcc inputbuffer(@@SPID)

(4) SQL Agent作业,在这里会被一并检查,也可以通过msdb..sysjobactivity另行检查;

select b.name, * 
  from msdb..sysjobactivity a
 inner join msdb.dbo.sysjobs b
    on a.job_id = b.job_id
 where b.name like '%backup%'

2. SQL Server 2000沿用过来的方法

select p.dbid, p.spid, p.blocked, p.waittime/1000.0/60.0 as wait_minutes, 
       ISNULL(DATEDIFF(MI, p.last_batch, GETDATE()), 0)elapsed_minutes, 
       p.last_batch, p.status, p.program_name, 
       (select [text] FROM::fn_get_sql(p.sql_handle)) sql_text
  from master..sysprocesses p
 where spid > 50 and spid <> @@SPID
  AND(status <> 'sleeping' AND ISNULL(DATEDIFF(MI, p.last_batch, GETDATE()), 0) > 30)

以上脚本返回运行超过30分钟的语句,需要注意的是:

sysprocesses中把connection/session/request信息三者合一,其中没有请求开始的具体时间,通过last_batch监视运行时长并不准确。测试如下:

(1) 通过ISQL连接到SQL Server,如果当前连接没发起过任何请求,last_batch的时间为 1900-01-01 00:00:00,在此连接上发起请求时,通过last_batch计算当前请求运行时长不准确;

(2) 在SQL Analyzer/SSMS中新建查询窗口,未发起任何查询时,last_batch与login_time一样,而非1900-01-01 00:00:00,通过last_batch计算当前请求运行时长不准确;或者当前窗口发起的请求已结束,但窗口/连接未关闭,则在此连接上再次发起请求,last_batch为上次请求结束的时间,通过last_batch计算当前请求运行时长也不准确;

(3) SQL Agent作业运行结束后,会把在sysprocesses的连接关闭,下次运行时重新建立连接,新建连接中last_batch等于login_time,通过last_batch计算作业运行时长准确;

作为一个老的方法,估且不再去深究,不过用sysprocesses来监视阻塞/等待还是没有问题的,另外作业的运行时长也是可以监视的,脚本改动后如下:

select p.dbid, p.spid, p.blocked, p.waittime/1000.0/60.0 as wait_minutes, 
       ISNULL(DATEDIFF(MI, p.last_batch, GETDATE()), 0)elapsed_minutes, 
       p.last_batch, p.status, p.program_name, 
       (select [text] FROM::fn_get_sql(p.sql_handle)) sql_text
  from master..sysprocesses p
 where spid > 50 and spid <> @@SPID
   and(
       (p.program_name like 'SQLAgent - TSQL JobStep (Job %' AND ISNULL(DATEDIFF(MI, p.last_batch, GETDATE()), 0) > 30)
       or 
       (p.blocked <> 0 and p.waittime/1000.0/60.0 > 30)
       )

这样一来,只剩下未被阻塞但长时间运行的sql请求未被监视到。如果一定要全面监视的话,可以选择开启跟踪,进而分析跟踪文件。

. 死锁

死锁的监控可以通过监视SQL Server的ERRORLOG来实现,不过需要事先打开死锁的跟踪标记。脚本如下:

--sql server 2000
dbcc traceon(1204,-1)
 
--sql server 2005 +
dbcc traceon(1222,-1)

这样发生死锁时,死锁详细信息就会被写入ERRORLOG,检查deadlock或者victim关键字即可进行监控。

小结

各个语句的运行时长/基线并不一样,通常不好设置统一的阀值,有时会借用第三方工具针对不同的请求设置不同的时长阀值并告警,所以在数据库这层大多告警阻塞即可,大致步骤如下 :

(1) 部署数据库邮件;

(2) 部署作业:定时检查阻塞,发邮件告警。

推荐阅读
  • 本文介绍了如何使用 PostgreSQL 的 `UPDATE ... FROM` 语法,通过映射表实现对多行记录进行高效的批量更新。这种方法不仅适用于单列更新,还支持多列的同时更新。 ... [详细]
  • PHP 编程疑难解析与知识点汇总
    本文详细解答了 PHP 编程中的常见问题,并提供了丰富的代码示例和解决方案,帮助开发者更好地理解和应用 PHP 知识。 ... [详细]
  • 构建基于BERT的中文NL2SQL模型:一个简明的基准
    本文探讨了将自然语言转换为SQL语句(NL2SQL)的任务,这是人工智能领域中一项非常实用的研究方向。文章介绍了笔者在公司举办的首届中文NL2SQL挑战赛中的实践,该比赛提供了金融和通用领域的表格数据,并标注了对应的自然语言与SQL语句对,旨在训练准确的NL2SQL模型。 ... [详细]
  • 本文详细介绍了HTML中标签的使用方法和作用。通过具体示例,解释了如何利用标签为网页中的缩写和简称提供完整解释,并探讨了其在提高可读性和搜索引擎优化方面的优势。 ... [详细]
  • 数据库内核开发入门 | 搭建研发环境的初步指南
    本课程将带你从零开始,逐步掌握数据库内核开发的基础知识和实践技能,重点介绍如何搭建OceanBase的开发环境。 ... [详细]
  • 本文深入探讨 MyBatis 中动态 SQL 的使用方法,包括 if/where、trim 自定义字符串截取规则、choose 分支选择、封装查询和修改条件的 where/set 标签、批量处理的 foreach 标签以及内置参数和 bind 的用法。 ... [详细]
  • 使用C#开发SQL Server存储过程的指南
    本文介绍如何利用C#在SQL Server中创建存储过程,涵盖背景、步骤和应用场景,旨在帮助开发者更好地理解和应用这一技术。 ... [详细]
  • 本文探讨了适用于Spring Boot应用程序的Web版SQL管理工具,这些工具不仅支持H2数据库,还能够处理MySQL和Oracle等主流数据库的表结构修改。 ... [详细]
  • 本文详细介绍了如何通过多种编程语言(如PHP、JSP)实现网站与MySQL数据库的连接,包括创建数据库、表的基本操作,以及数据的读取和写入方法。 ... [详细]
  • 在当前众多持久层框架中,MyBatis(前身为iBatis)凭借其轻量级、易用性和对SQL的直接支持,成为许多开发者的首选。本文将详细探讨MyBatis的核心概念、设计理念及其优势。 ... [详细]
  • 在使用 DataGridView 时,如果在当前单元格中输入内容但光标未移开,点击保存按钮后,输入的内容可能无法保存。只有当光标离开单元格后,才能成功保存数据。本文将探讨如何通过调用 DataGridView 的内置方法解决此问题。 ... [详细]
  • 本文详细介绍了如何在 Linux 平台上安装和配置 PostgreSQL 数据库。通过访问官方资源并遵循特定的操作步骤,用户可以在不同发行版(如 Ubuntu 和 Red Hat)上顺利完成 PostgreSQL 的安装。 ... [详细]
  • 如何在PostgreSQL中查看数据表
    本文将指导您使用pgAdmin工具连接到PostgreSQL数据库,并展示如何浏览和查找其中的数据表。通过简单的步骤,您可以轻松访问所需的表结构和数据。 ... [详细]
  • 利用存储过程构建年度日历表的详细指南
    本文将介绍如何使用SQL存储过程创建一个完整的年度日历表。通过实例演示,帮助读者掌握存储过程的应用技巧,并提供详细的代码解析和执行步骤。 ... [详细]
  • 本文介绍了如何通过 Maven 依赖引入 SQLiteJDBC 和 HikariCP 包,从而在 Java 应用中高效地连接和操作 SQLite 数据库。文章提供了详细的代码示例,并解释了每个步骤的实现细节。 ... [详细]
author-avatar
手机用户2502937541
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有