设为首页 收藏本站
查看: 989|回复: 0

[经验分享] Silverlight实现对Sql Server Profiler的SQL实时监控

[复制链接]
YunVN网友  发表于 2015-6-26 18:49:07 |阅读模式
  Sql Server Profiler作为Microsoft Sql Server数据库系列的性能工具,通过它可以对数据库的运行状况进行实时跟踪,从中可以找到慢查询或者死锁的SQL语句,从而去优化系统。本文介绍如果通过Silverlight来对Sql Server Profiler进行实时监控(数据库环境以Sql Server 2005为例)
  
  首先,先来看下SqlServer数据库自带的性能工具Sql Server Profiler,新建一个跟踪: DSC0000.png
  我们选择默认的模板Standard,其他都不变,点击运行:
DSC0001.png
  从中可以看到数据库中的SQL的运行状态,EventClass作为事件类型,TextData作为运行的SQL脚本,ApplicationName作为一个应用程序的执行源的名称,比如说,从.Net应用程序执行的SQL脚本就是.Net SqlClient Data Provider,再比如说,我直接从数据库客户端工具执行一条SQL语句,可以看到ApplicationName为 ”Microsoft SQL Server Management Studio - 查询“,因此我们通过ApplicationName字段得到程序的执行源,LoginName作为一个数据库的账户,一般系统用户为sa,包括CPU/Reads/Writes在此上面也是一目了然,Duration比较有用,可以查看执行语句的耗时,后面还包括StartTime的开始时间和EndTime的结束时间,当然一些隐藏的列我就不一一列举了,有兴趣大家可以勾选查看下。
  如果我要定义一个符合自己需要的模板呢,那么可以通过新建/编辑模板来实现:
DSC0002.png
  上面有很多的事件类型的选择,可以根据自己的需要定制Event,这里我以最简单的方式,就选择了TSQL:SQL BatchCompleted:
DSC0003.png
  并且列选择一个数据库DatabaseName,类似于编辑 MyEnt,这样该模板文件只会在MyEnt为名称的数据库中进行SQL执行跟踪了:
DSC0004.png
  最后点击保存即可
  
  那么,在.Net上怎么实现对于Sql Server Profiler的使用和监控,实际上,Sql ServerProfiler本身为.Net开发的,后来我在SqlServer2005数据库的安装目录 C:\Program Files\Microsoft SQL Server\90\SDK\Assemblies 中,找到一个Microsoft.SqlServer.ConnectionInfo.dll,这个dll就可以实现执行Sql的监控。
  开始创建项目,其中,监控程序是一个控制台程序,而Silverlight客户端程序是一个对于SqlServerProfiler实时监控的展示,Silverlight的客户端程序通过Socket和监控程序进行通信。由于Silverlight对于TCP通信的限制,必须往监控程序发送策略请求,并且对于TCP通信来说,目前Silverlight的使用端口必须为4502-4530,于是必须在监控端先设置一个Policy.xml的策略文件:




   
     
      
         
      
      
         
      
     
   
  现在我将策略请求,监听SL客户端连接/数据收发请求,数据库监听跟踪请求,分别创建3个线程:
  //创建Socket来监听策略请求和发送



this._policyThread = this.CreateThread(this.PolicyRequest);
//创建Socket来监听信息请求和发送
this._infoThread = this.CreateThread(this.InfoRequest);
//创建Socket来监听数据库跟踪请求和发送
this._traceServerThread = this.CreateThread(this.TraceServerRequest);   PolicyRequest,InfoRequest的方法具体看文章末尾的附件源代码,这里主要说一下TraceServerRequest的方法:


SqlConnectionInfo conninfo = new SqlConnectionInfo();
conninfo.ServerName = "机器名";
conninfo.UserName = "数据库账户";
conninfo.Password = "数据库密码";
conninfo.UseIntegratedSecurity = false;
TraceServer trace = new TraceServer();
trace.InitializeAsReader(conninfo, TDF_FILE);
SqlConnectionInfo, TraceServer类来自于对Microsoft.SqlServer.ConnectionInfo的引用,其中TDF_FILE就是我前面说的跟踪模板文件名,它的文件后缀为tdf。
while (trace.Read())
{
    var eventData = new EventData()
    {
        EventClass = trace["EventClass"].ToString(),
        TextData = trace["TextData"] != null ? trace["TextData"].ToString() : "",
        ApplicationName = trace["ApplicationName"] != null ? trace["ApplicationName"].ToString() : "",
        NTUserName = trace["NTUserName"] != null ? trace["NTUserName"].ToString() : "",
        LoginName = trace["LoginName"] != null ? trace["LoginName"].ToString() : "",
        CPU = trace["CPU"] != null ? trace["CPU"].ToString() : "",
        Reads = trace["Reads"] != null ? trace["Reads"].ToString() : "",
        Writes = trace["Writes"] != null ? trace["Writes"].ToString() : "",
        Duration = trace["Duration"] != null ? trace["Duration"].ToString() : "",
        ClientProcessID = trace["ClientProcessID"] != null ? trace["ClientProcessID"].ToString() : "",
        SPID = trace["SPID"] != null ? trace["SPID"].ToString() : "",
        StartTime = trace["StartTime"] != null ? trace["StartTime"].ToString() : "",
        EndTime = trace["EndTime"] != null ? trace["EndTime"].ToString() : "",
    };
    var sendData = JsonConvert.SerializeObject(eventData);
    if (string.IsNullOrEmpty(sendData))
        continue;
    lock (_lock)
    {
        this._queues.Enqueue(sendData);
    }
}   通过trace.Read()方法来得到trace的跟踪记录,这里我不会马上通过Socket发送到SL客户端,而是通过一个队列对跟踪记录进行人队,通过InfoRequest从队列中取出数据,发送给SL客户端:


while (true)
{
     lock (_lock)
     {
         if (this._queues.Count == 0)
         {
             Thread.Sleep(200);
             continue;
         }
         var sendData = this._queues.Dequeue();
         Console.WriteLine(sendData);
         byte[] data = Encoding.GetEncoding("gb2312").GetBytes(sendData);
         // 移除已断开的套接字
         this._clientList.RemoveAll(o => o.Connected == false);
         foreach (Socket s in this._clientList)
         {            
             if (s.Connected)
             {
                 try
                 {
                     //发送数据
                     s.Send(data);
                 }
…
  SL客户端通过Socket异步编程接收数据


///  
/// 当接收完成
///  
///  
void ProcessReceive(SocketAsyncEventArgs e)
{
     if (e.SocketError == SocketError.Success)
     {
         try
         {
             Gb2312Encoding encoding = new Gb2312Encoding();
   
             string data = Regex.Replace(encoding.GetString(e.Buffer, 0, e.Buffer.Length), @"\0", "");
   
             EventData eventData = JsonConvert.DeserializeObject(data);
             byte[] bytes = new byte[1024];
             e.SetBuffer(bytes, 0, bytes.Length);
             this._syn.Send(this.GetText, eventData);
             //执行连接
             this._socket.ReceiveAsync(this._socketArgs);   
         }
…
//同步上下文调用的方法
private void GetText(object data)
{
    if (data == null)
        return;
    EventData eventData = (EventData)data;
    _list.Add(eventData);
    this.Dispatcher.BeginInvoke(new Action(() =>
    {
        this.dataGridRecords.ItemsSource = null;
        this.dataGridRecords.ItemsSource = _list;
        this.dataGridRecords.UpdateLayout();
        this.dataGridRecords.SelectedIndex = _list.Count - 1;
        this.dataGridRecords.ScrollIntoView(this.dataGridRecords.SelectedItem, null);
    }));
}   这样就实现了Silverlight客户端对于Sql Server Profiler的实时监控。
  两个项目很简单:
DSC0005.png
  先运行 SqlServerProfier.Host程序:
DSC0006.png
  正在对外发送监控数据,
  然后运行宿主SL客户端程序的Web端:
DSC0007.png
  如果是慢查询的部分,我会用红色把它标红,从而确定慢查询语句,优化系统
  
  总结:
  当然,你还可以在监控程序中,对于跟踪记录进行Log写入或者一个特定Log表的插入,通过Web端(不管是Silverlight还是asp.net mvc均可以查询相关的跟踪记录),从而达到对于数据库SQL执行的监控。
  
  附上源代码:SqlServerProfiler.rar

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-80812-1-1.html 上篇帖子: SQL SERVER 表分区 下篇帖子: 在SQL Server实现最短路径的搜索
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表