当前位置: 代码网 > it编程>数据库>MsSqlserver > SQLServer监控阻塞会话的方法

SQLServer监控阻塞会话的方法

2024年06月13日 MsSqlserver 我要评论
一、查询阻塞和被阻塞的会话select r.session_id as [blocked session id], r.blocking_session_id as [blocking

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

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);
    }
}

说明

  • 连接字符串:替换 your_connection_string_here 为实际的数据库连接字符串。
  • 定时器:使用 system.timers.timer 类设置每10秒执行一次检查。
  • 检查阻塞会话:在 checkforblockingsessions 方法中,查询阻塞会话和根源会话的信息。
  • 终止会话:在 killsession 方法中,执行 kill 命令来终止阻塞会话。
  • 日志记录:日志记录包括阻塞会话的详细信息和终止会话的操作,以及错误信息。

注意事项

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

到此这篇关于sqlserver如何监控阻塞会话的文章就介绍到这了,更多相关sqlserver阻塞会话内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com