首页 > 数据库 >SQLServer如何监控阻塞会话

SQLServer如何监控阻塞会话

时间:2024-05-28 09:58:09浏览次数:18  
标签:string SQLServer 阻塞 会话 session logMessage using id

一、查询阻塞和被阻塞的会话

复制代码
SELECT 
    r.session_id AS [Blocked Session ID],
    r.blocking_session_id AS [Blocking Session ID],
    r.wait_type,
    r.wait_time,
    r.wait_resource,
    s1.program_name AS [Blocked Program Name],
    s1.login_name AS [Blocked Login],
    s2.program_name AS [Blocking Program Name],
    s2.login_name AS [Blocking Login],
    r.text AS [SQL Text]
FROM sys.dm_exec_requests AS r
LEFT JOIN sys.dm_exec_sessions AS s1 ON r.session_id = s1.session_id
LEFT JOIN sys.dm_exec_sessions AS s2 ON r.blocking_session_id = s2.session_id
CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) AS r
WHERE r.blocking_session_id <> 0;
复制代码

二、找出阻塞的具体SQL

复制代码
SELECT 
    r.session_id,
    r.blocking_session_id,
    t.text AS [SQL Text],
    r.wait_type,
    r.wait_time,
    r.wait_resource
FROM sys.dm_exec_requests AS r
CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) AS t
WHERE r.blocking_session_id <> 0;
复制代码

三、编写C#程序,每隔10秒监控SQL Server数据库中的阻塞会话,定位出阻塞的根源会话并终止它们,同时记录日志。

复制代码
using System;
using System.Data.SqlClient;
using System.IO;
using System.Timers;

class Program
{
    private static Timer timer;
    private static string connectionString = "your_connection_string_here";

    static void Main(string[] args)
    {
        timer = new Timer(10000); // 每10秒执行一次
        timer.Elapsed += CheckForBlockingSessions;
        timer.AutoReset = true;
        timer.Enabled = true;

        Console.WriteLine("Press [Enter] to exit the program.");
        Console.ReadLine();
    }

    private static void CheckForBlockingSessions(object source, ElapsedEventArgs e)
    {
        try
        {
            using (SqlConnection connection = new SqlConnection(connectionString))
            {
                connection.Open();

                string query = @"
                SELECT 
                    r.session_id AS BlockedSessionID,
                    r.blocking_session_id AS BlockingSessionID,
                    r.text AS SqlText
                FROM sys.dm_exec_requests AS r
                CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) AS r
                WHERE r.blocking_session_id <> 0;";

                using (SqlCommand command = new SqlCommand(query, connection))
                {
                    using (SqlDataReader reader = command.ExecuteReader())
                    {
                        while (reader.Read())
                        {
                            int blockedSessionId = reader.GetInt32(0);
                            int blockingSessionId = reader.GetInt32(1);
                            string sqlText = reader.GetString(2);

                            LogBlockingSession(blockedSessionId, blockingSessionId, sqlText);
                            KillSession(blockingSessionId);
                        }
                    }
                }
            }
        }
        catch (Exception ex)
        {
            LogError(ex.Message);
        }
    }

    private static void KillSession(int sessionId)
    {
        try
        {
            using (SqlConnection connection = new SqlConnection(connectionString))
            {
                connection.Open();
                string killQuery = $"KILL {sessionId};";
                using (SqlCommand killCommand = new SqlCommand(killQuery, connection))
                {
                    killCommand.ExecuteNonQuery();
                    LogKillSession(sessionId);
                }
            }
        }
        catch (Exception ex)
        {
            LogError($"Failed to kill session {sessionId}: {ex.Message}");
        }
    }

    private static void LogBlockingSession(int blockedSessionId, int blockingSessionId, string sqlText)
    {
        string logMessage = $"[{DateTime.Now}] Blocked Session ID: {blockedSessionId}, Blocking Session ID: {blockingSessionId}, SQL Text: {sqlText}";
        File.AppendAllText("blocking_sessions.log", logMessage + Environment.NewLine);
        Console.WriteLine(logMessage);
    }

    private static void LogKillSession(int sessionId)
    {
        string logMessage = $"[{DateTime.Now}] Killed Session ID: {sessionId}";
        File.AppendAllText("killed_sessions.log", logMessage + Environment.NewLine);
        Console.WriteLine(logMessage);
    }

    private static void LogError(string message)
    {
        string logMessage = $"[{DateTime.Now}] Error: {message}";
        File.AppendAllText("errors.log", logMessage + Environment.NewLine);
        Console.WriteLine(logMessage);
    }
}
复制代码

说明

  1. 连接字符串:替换 your_connection_string_here 为实际的数据库连接字符串。
  2. 定时器:使用 System.Timers.Timer 类设置每10秒执行一次检查。
  3. 检查阻塞会话:在 CheckForBlockingSessions 方法中,查询阻塞会话和根源会话的信息。
  4. 终止会话:在 KillSession 方法中,执行 KILL 命令来终止阻塞会话。
  5. 日志记录:日志记录包括阻塞会话的详细信息和终止会话的操作,以及错误信息。

注意事项

  • 运行此程序需要确保有足够的权限来访问数据库和执行 KILL 命令。
  • 请仔细测试程序以确保其符合预期行为,尤其是在生产环境中。
  • 日志文件的路径和权限需要根据实际情况进行配置。

周国庆

2024/5/28

 

2024-05-28 09:42:48【出处】:https://www.cnblogs.com/tianqing/p/18217020

=======================================================================================

标签:string,SQLServer,阻塞,会话,session,logMessage,using,id
From: https://www.cnblogs.com/mq0036/p/18217171

相关文章

  • SQLServer统计监控SQL执行计划突变的方法
    使用动态管理视图(DMVs)来检测SQL执行计划的突变,你需要关注那些能够提供查询执行统计和计划信息的视图。以下是一些可以用于此目的的DMVs以及相应的查询示例:sys.dm_exec_query_stats:这个视图提供了关于SQLServer中查询执行的统计信息,包括CPU时间、总工作时间、执行次数等。SE......
  • SQLServer如何监控阻塞会话
    一、查询阻塞和被阻塞的会话SELECTr.session_idAS[BlockedSessionID],r.blocking_session_idAS[BlockingSessionID],r.wait_type,r.wait_time,r.wait_resource,s1.program_nameAS[BlockedProgramName],s1.login_nameAS[Block......
  • [UDS诊断 03- 诊断会话控制(0x10)]-深度解读
     1.诊断会话       诊断会话模式由诊断服务层用于访问受限于特定会话的不同诊断服务。节点需要支持若干会话模式,如下所示:诊断会话定义    非默认会话启动时,控制器应启动S3_server定时器。如果在这个时间范围内没有从任何一......
  • 数组类型的有界阻塞队列-ArrayBlockingQueue
    一:ArrayBlockingQueue简介  一个由循环数组支持的有界阻塞队列。它的本质是一个基于数组的BlockingQueue的实现。它的容纳大小是固定的。此队列按FIFO(先进先出)原则对元素进行排序。队列的头部是在队列中存在时间最长的元素。队列的尾部是在队列中存在时间最短的元素。......
  • 非阻塞sokcet和epoll
    在Muduo网络库中同时使用了非阻塞socket与epoll,在此简单梳理下。非阻塞sokcet和epoll共同工作的过程主要涉及网络编程中的非阻塞I/O和事件驱动机制。下面将详细解释这两者如何协同工作:非阻塞socket简介在传统的阻塞socket编程中,当调用如read、write、accept等函数时,如果当......
  • SQLServer通过发布订阅实现主从同步(读写分离)
    发布订阅实操:(1).启动SQLServer代理模式。 PS:从库也可以不用创建,因为在新建订阅的时候,可以选择自动创建,会自动同步数据库结构。 1.配置分发服务器(1). 如果是首次配置读写分离,需要配置分发服务器,后续不再配置。 如果不想用之前的分发服务器,可以右键复制,禁用分发服务器......
  • 磁盘被sqlserver日志文件占满如何处理
    因为磁盘已经被占满,使用分离附加方法也失败,故只能直接从磁盘中删除ldf文件。接下来的问题是,如何在没有ldf文件的情况下恢复数据库mdf文件呢如图所示,新建数据库TestLDF,生成mdf和ldf文件 现在模拟删除ldf文件,点击继续,弹出文件正在使用,停止sqlserver服务再次删除ldf文件,删除成......
  • QT使用串口通信点击主界面通信阻塞
    1.问题导入在使用QT进行串口上位机开发时遇到鼠标点击主界面导致串口接收数据阻塞,无法继续在QT控件中更新接收到的数据。2.解决办法使用多线程:将串口通信放入子线程中。`QSerialPort*UARTDevide;//串口UART*newUART;//串口类QThreadUARTThred;//串口线程newUART->mo......
  • 在SQLServer中使用SQL语句插入数据出现乱码或问号的解决方法
    原文链接:https://www.cnblogs.com/net5x/p/12430808.html错误产生的原因:        出现使用SQL语句插入数据出现乱码或问号是由于数据库属性的排序规则设置不正确.解决方法:方法一:手动修改(设置数据库的排序规则)注意事项:要确定修改的数据库没有被使用,否则会失败!具体步骤......
  • 关于SQLServer数据库的READ_COMMITTED_SNAPSHOT隔离级别
    默认情况下,SQLServer的事务隔离级别是READCOMMITED。刚开始我理解这个模式就是读已经提交的,那也就是说并发一个事务去更新,一个事务查询同一条数据应该是像Mysql、Oracle不会加锁直接返回数据库已经提交的数据才对。但是SQLServer不是这样的。SQLServer中有READ_COMMITTED_SN......