Silverlight實現對Sql Server Profiler的SQL實時監控


      Sql Server Profiler作為Microsoft Sql Server數據庫系列的性能工具,通過它可以對數據庫的運行狀況進行實時跟蹤,從中可以找到慢查詢或者死鎖的SQL語句,從而去優化系統。本文介紹如果通過Silverlight來對Sql Server Profiler進行實時監控(數據庫環境以Sql Server 2005為例)

 

      首先,先來看下SqlServer數據庫自帶的性能工具Sql Server Profiler,新建一個跟蹤:image

我們選擇默認的模板Standard,其他都不變,點擊運行:

image

從中可以看到數據庫中的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的結束時間,當然一些隱藏的列我就不一一列舉了,有興趣大家可以勾選查看下。

      如果我要定義一個符合自己需要的模板呢,那么可以通過新建/編輯模板來實現:

image

上面有很多的事件類型的選擇,可以根據自己的需要定制Event,這里我以最簡單的方式,就選擇了TSQL:SQL BatchCompleted:

image

並且列選擇一個數據庫DatabaseName,類似於編輯 MyEnt,這樣該模板文件只會在MyEnt為名稱的數據庫中進行SQL執行跟蹤了:

image

最后點擊保存即可

 

      那么,在.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的策略文件:

<? xml version="1.0" encoding ="utf-8" ?> 
< access-policy > 
   < cross-domain-access > 
     < policy > 
       < allow-from > 
         < domain  uri ="*"   /> 
       </ allow-from > 
       < grant-to > 
         < socket-resource  port ="4502-4530"  protocol ="tcp"   /> 
       </ grant-to > 
     </ policy > 
   </ cross-domain-access > 
</ access-policy >

現在我將策略請求,監聽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異步編程接收數據

///   <summary>  
///  當接收完成 
///   </summary>  
///   <param name="e"></param>  
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<EventData>(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的實時監控。

兩個項目很簡單:

image

先運行 SqlServerProfier.Host程序:

image

正在對外發送監控數據,

然后運行宿主SL客戶端程序的Web端:

image

如果是慢查詢的部分,我會用紅色把它標紅,從而確定慢查詢語句,優化系統

 

總結:

      當然,你還可以在監控程序中,對於跟蹤記錄進行Log寫入或者一個特定Log表的插入,通過Web端(不管是Silverlight還是asp.net mvc均可以查詢相關的跟蹤記錄),從而達到對於數據庫SQL執行的監控。

 

附上源代碼:SqlServerProfiler.rar


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM