2012-08-24 15 views
7

環境ハング:(.NET 4のC#で書かれた)ADO.Net SQLCommand.ExecuteReader()は、減速又は

アプリケーション10スレッドまで有し、各スレッドは、独自のアプリケーションドメインで実行されます。各スレッドは、SQL Server 2008のストアドプロシージャから結果を取得するADO.Net DataReaderを使用します。また、スレッドはADO.Netを使用して書き込み操作(一括挿入)を実行できます。すべてがローカルマシン上で実行されます。

問題#1:

時々(約各30日の実行)、スレッドの実行が大幅に遅くなります。これは、DataReaderがストアドプロシージャの結果(SqlCommand.ExecuteReader())を取得したときに発生します。通常、読み取り操作は10秒で実行されます。それが減速すると、10〜20分で実行されます。 SQLProfilerは、非常にゆっくりですが、データが照会されていることを示します。

減速のコールスタック(例外がないことに注意してください):

at SNIReadSync(SNI_Conn* , SNI_Packet** , Int32) 
    at SNINativeMethodWrapper.SNIReadSync(SafeHandle pConn, IntPtr& packet, Int32 timeout) 
    at System.Data.SqlClient.TdsParserStateObject.ReadSni(DbAsyncResult asyncResult, TdsParserStateObject stateObj) 
    at System.Data.SqlClient.TdsParserStateObject.ReadNetworkPacket() 
    at System.Data.SqlClient.TdsParserStateObject.ReadBuffer() 
    at System.Data.SqlClient.TdsParserStateObject.ReadByteArray(Byte[] buff, Int32 offset, Int32 len) 
    at System.Data.SqlClient.TdsParserStateObject.ReadString(Int32 length) 
    at System.Data.SqlClient.TdsParser.ReadSqlStringValue(SqlBuffer value, Byte type, Int32 length, Encoding encoding, Boolean isPlp, TdsParserStateObject stateObj) 
    at System.Data.SqlClient.TdsParser.ReadSqlValue(SqlBuffer value, SqlMetaDataPriv md, Int32 length, TdsParserStateObject stateObj) 
    at System.Data.SqlClient.SqlDataReader.ReadColumnData() 
    at System.Data.SqlClient.SqlDataReader.ReadColumnHeader(Int32 i) 
    at System.Data.SqlClient.SqlDataReader.ReadColumn(Int32 i, Boolean setTimeout) 
    at System.Data.SqlClient.SqlDataReader.GetValueInternal(Int32 i) 
    at System.Data.SqlClient.SqlDataReader.GetValue(Int32 i) 
    at System.Data.SqlClient.SqlDataReader.get_Item(String name) 
    at ****.Core.TableDataImporter.ImportDataFromExcel(Int32 tableId, ExcelEntityLocation location, Boolean& updateResult) in … 

問題#2:

代わりにスレッドがハングアップすることができます減速の。

コールスタック:

at SNIReadSync(SNI_Conn* , SNI_Packet** , Int32) 
    at SNINativeMethodWrapper.SNIReadSync(SafeHandle pConn, IntPtr& packet, Int32 timeout) 
    at System.Data.SqlClient.TdsParserStateObject.ReadSni(DbAsyncResult asyncResult, TdsParserStateObject stateObj) 
    at System.Data.SqlClient.TdsParserStateObject.ReadNetworkPacket() 
    at System.Data.SqlClient.TdsParserStateObject.ReadBuffer() 
    at System.Data.SqlClient.TdsParserStateObject.ReadByte() 
    at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj) 
    at System.Data.SqlClient.SqlDataReader.ConsumeMetaData() 
    at System.Data.SqlClient.SqlDataReader.get_MetaData() 
    at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString) 
    at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async) 
    at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result) 
    at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method) 
    at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method) 
    at System.Data.SqlClient.SqlCommand.ExecuteReader() 

コールスタックは、バックグラウンドスレッドでデバッグツールを使用して取得しました。遅れやハングアップのいずれの例外も起こりません。

SNIReadSyncは、ネットワークレベルで動作し、ネットワーク経由でパケットを送信するメカニズムです。ローカルマシン上でこの問題を再現し、ネットワークの問題を除外しています。

私たちは、この減速/ハングアップのための入力と解決策または回避策を探しています。今のところ、減速を検出して操業を再開する計画です。前もって感謝します。

要求されるように、私は方法のために単純化されたコードを追加しています:

public void ImportDataFromExcel() 
    {    
     try 
     {     
      var _сonnectionBuilk = ... ; // singleton connection (at the app level) 
      var spName = ... ; // stored procedure name 

     var сonnectionToRead = new SqlConnection(connectionStirng); 
     сonnectionToRead.Open(); 

     var sqlCommand = new SqlCommand(spName); 
     sqlCommand.CommandType = CommandType.StoredProcedure; 
     sqlCommand.Parameters.Add(param1Name, SqlDbType.Int).Value = ...; 
     sqlCommand.Parameters.Add(param2Name, SqlDbType.Int).Value = ...; 
     sqlCommand.Parameters.Add(param2Name, SqlDbType.Int).Value = ...; 

     sqlCommand.Connection = сonnectionToRead;    
     sqlCommand.CommandTimeout = timeout; // 120 sec 

     using (var dataReader = sqlCommand.ExecuteReader()) 
     { 
       dataReader.Read(); 
      ..... 
      int pos1 = dataReader.GetOrdinal(columnName1); 
      int pos2 = dataReader.GetOrdinal(columnName2); 
      int pos3 = dataReader.GetOrdinal(columnName3); 
      int pos4 = dataReader.GetOrdinal(columnName4); 
       .....      

      // reading data from sqldatareader 
      int val1 = dataReader.GetInt32(pos1); 
      int val2 = dataReader.GetInt32(pos2); 
      int val3 = dataReader.GetInt32(pos3); 
      var val4 = dataReader.GetDateTime(pos4); 
      ..... 

      // append read data into bulkTable 
      bulkTable.AddCellValue(val1, val2, val3, val4); // bulkTable wraps DataTable, and appends DataRow inside. 

      if(bulkTable.DataTable.Rows > MaxRowsCount) 
      { 
       using (var bulkCopy = new SqlBulkCopy(_сonnectionBuilk)) 
       { 
        bulkCopy.DestinationTableName = _fullTableName; 
        bulkCopy.WriteToServer(bulkTable.DataTable); 
       } 

       var sqlCommandTransfer = new SqlCommand(spName); 
       sqlCommandTransfer.CommandType = CommandType.StoredProcedure; 
       sqlCommandTransfer.Parameters.Add(param1Name, SqlDbType.Int).Value = ...; 
       sqlCommandTransfer.Connection = _сonnectionBuilk; 
       .... 
       sqlCommandTransfer.ExecuteNonQuery(); // transfering data from temp bulk table into original table 
      } 
     } 
    } 
    finally 
    { 
     bulkTable.Dispose(); 
     сonnectionToRead.Close(); 
    } 
} 
+1

コードを表示できますか?特に、作成、オープン、接続のクローズ、リーダーの実行を行う場所。 –

+2

これはdb側の問題のように聞こえます。 SQL上に定期的に実行されるワーカープロセスがありますか?行/テーブルロックを引き起こしている同期または何らかのアクション?どのくらいのテーブルが関与していますか?どのようなインデックス/制約の種類など – Brian

+0

@ TimSchmelter - 私はハングするコードを追加しました。 – Cortlendt

答えて

1

をコードはしばらくの間、完璧に動作しますので、我々はそれを絞り込むことができます。

  • あなたから遮断するデータベースのロック/プロセスなどがあります。
  • プロセスからのデータベースのロック/ブロックのみ。
  • ネットワーク接続。
  • データの状態。
  • サーバー上のディスクスペースまたは他の一見無関係な問題。

私は、おそらくデータベースのロック/ブロックの問題だと思います。しかし、あなたは本当にこれを確かめる必要があります。これを行うには、

  • データベースログとその他のログを含めて、データベースの書き込み先ディスクスペースがあることを確認してください。
  • 他のプロセスがデータベースを使用していないことを確認してください。
  • ネットワークの問題を解消するために、ローカルデータベースも使用することをお勧めします。
  • .Net 4 - を使用しているので、タスクを使用している場合、それらを過負荷と同期して実行するのは非常に簡単です。これを行い、問題がまだ存在するかどうかを確認します。

上記をすべて実行すると、問題が解決されるはずです。そこからさらに絞り込むことができます。

3

我々は数ヶ月のために同様の問題をデバッグしようとし、そして最終的に今日それを追跡してきた...

我々はcalliong ToListメソッド/てToArrayは/ etcなし(キャッシュに隠されていたクエリを持っていました。それに)。このクエリは、その後クリーンアップされた接続に結び付けられ、[コード] ReadSni [/ code](完全なスタックは以下に含まれています)からCPUを100%ブロックしたように見えます。

私は、クエリがLinqを使用するように変更される前に書かれていたと考えています(リストを返す代わりに、IEumberableとしてキャストします)ので、誰かがデータアクセスを「怠け者」にしたときに導入されました。

なぜ数日ごとに生産されたのか説明できません。キャッシュが大量に使用されていないか、接続が特定の状態になってこのように失敗するかのいずれかです。

[コード] OSスレッドID:0x20b8(27) 託児SP IPコールサイト 16edd0fcの6184267eのSystem.Data.SqlClient.TdsParserStateObject.ReadSni(System.Data.Common.DbAsyncResult、System.Data.SqlClient.TdsParserStateObject ) 16edd134 61842624 System.Data.SqlClient.TdsParserStateObject.ReadNetworkPacket() 16edd144 618446af System.Data.SqlClient.TdsParserStateObject.ReadBuffer() 16edd150 61c583d0 System.Data.SqlClient.TdsParserStateObject.CleanWire() 16edd15c 61d1beb9 System.Data。 System.Data.SqlClient.SqlInternalConnectionTds.InternalDeactivate() 16edd174 1684995f dd180 61849640 System.Data.SqlClient.SqlInternalConnection.Deactivate() 16edd1b0 61849587 System.Data.ProviderBase.DbConnectionInternal.DeactivateConnection() 16edd1e4 61849405 System.Data.ProviderBase.DbConnectionPool.DeactivateObject(System.Data.ProviderBase.DbConnectionInternal) 16edd224 61849384 System.Data.ProviderBase.DbConnectionPool.PutObject(System.Data.ProviderBase.DbConnectionInternal、System.Object) 16edd26c 6184920c System.Data.ProviderBase.DbConnectionInternal.CloseConnection(System.Data.Common.DbConnection、System.Data.ProviderBase。 DbConnectionFactory) 16edd2ac 618490f7 System.Data.SqlClient.SqlInternalConnection.CloseConnection(System.Data.Common.DbConnection、System.Data.ProviderBase.DbConnectionFactory) 16edd2c4 618393bf System.Data.SqlClient.SqlConnection.Close() 16edd304 11238f0a NHibernate.Connection.ConnectionProvider.CloseConnection(System.Data.IDbConnection) 16edd340 11238eae NHibernate.Connection.DriverConnectionProvider.CloseConnection(System.Data.IDbConnection) 16edd34c 11aceb42 NHibernate.AdoNet.ConnectionManager.CloseConnection() 16edd358 11aceb02 NHibernateは.AdoNet.ConnectionManager.AggressiveRelease() 16edd364 11acf783 NHibernate.AdoNet.ConnectionManager.AfterTransaction() 16edd370 11acf6d1 NHibernate.Impl.SessionImpl.AfterTransactionCompletion(ブール、NHibernate.ITransaction) 16edd3ec 11acf5de NHibernate.AdoNet.ConnectionManager.AfterNonTransactionalQuery(ブール) 16edd3fc 11acf539 NHibernate.Impl.AbstractSessionImpl.AfterOperation(Boolean) 16edd474 130311e4 NHibe (NHibernate.IQueryExpression、NHibernate.Engine.QueryParameters、System.Collections.IList) 16ede51c 13031071 NHibernate.Impl。AbstractSessionImpl.List(NHibernate.IQueryExpression、NHibernate.Engine.QueryParameters) 16ede538 13030b68 NHibernate.Impl.ExpressionQueryImpl.List() 16ede568 13030a47 NHibernate.Linq.DefaultQueryProvider.ExecuteQuery(NHibernate.Linq.NhLinqExpression、NHibernate.IQuery、NHibernate.Linq .NhLinqExpression) 16ede59c 11d4c163 NHibernate.Linq.DefaultQueryProvider.Execute(System.Linq.Expressions.Expression) 16ede5b0 11d4c108 NHibernate.Linq.DefaultQueryProvider.Execute [SYSTEM._ キヤノン、mscorlib] 16ede5c4 11d4c0a6 Remotion.Linq.QueryableBase 1[[System.__Canon, mscorlib]].GetEnumerator() 16ede5d4 61022108 System.Linq.Enumerable+WhereEnumerableIterator 1 [[System。 。 _Canon、mscorlib]] MoveNextメソッド()* WARNING:System.Core.ni.dll * ERRORのチェックサムを確認することができません:モジュールのロードが完了したが、シンボルはSystem.Core.ni.dll

のためにロードできませんでした

16ede5e4 610166ea System.Linq.Buffer 1[[System.__Canon, mscorlib]]..ctor(System.Collections.Generic.IEnumerable 1) 16ede620 6122e171 System.Linq.OrderedEnumerable 1+<GetEnumerator>d__0[[System.__Canon, mscorlib]].MoveNext() 16ede63c 79b39758 System.Collections.Generic.List 1 [システム.__キヤノン、mscorlib]] .. CTOR(System.Collections.Generic.IEnumerable`1)* WARNING:できません。 mscorlib.ni.dllのチェックサムを確認するには *エラー:モジュールの読み込みが完了しましたが、mscorlib.ni.dllのシンボルを読み込めませんでした。

System.Linq.Enumerable.ToList 61021acf 0

16ede66c "> [システム.__キヤノン、mscorlib] [/コード]

+0

問題を解決できましたか?もしそうなら、それはSQLサーバー側、ADO.NET側、またはコード変更上の構成上の問題でしたか? – cortijon

+1

コードが変更されました。キャッシュにアイテムを置く前にToList()を呼び出して、評価されていない列挙の代わりに実際のアイテムがキャッシュされました。それ以来、我々はそれを見たとは思わない:-) –

0

私は同じ問題を抱えていたし、私は私の特定のケースについて話いくつかのテストの後に解決しますが、私は思いますそれは役に立つかもしれない。

私のシステムでは、SQLServer 2008で複雑なOLAPエンジンを使用しています。 長年にわたり、操作量と量が増加し、ランダムに私はエラーを取り除きました。私はすべての操作OLAPのコードをチェックし、すべてのトランザクション、接続、および読者オブジェクトは完全に処理されました。生成された

臨界点エラー、私はWHILEのセクションでは、SQLServerのために照会するループしたとき(常にではない)、querysの繰り返し爆撃が

ホーristrutturatoルmolte piccole querysでUNAクエリよりたくさんのDBでエラーが発生しました大统领(终了效果)は、LINQ、オペラ座、オペラ座、オペラ座、オペラ座、オペラ座、過渡期10ボルトで誤差が生じます。

私が与えることができるアドバイスは、コードのクリティカルセクションをよく分析することです.Connection、DataReader、Transactionをどのように使用するかは非常に注意してください。