2010-11-23 17 views
2

私は最近、次のようなエラーを投げて開始したウェブサイトがあります。ASP.NET SQL ServerのConsumePreLoginHandshake十分なメモリがありません例外

public static List<Link> GetTopLinks() 
     { 
      List<Link> lLinks = new List<Link>(); 

      try 
      { 
       using(DbCommand dbCommand = GenericDataAccess.CreateCommand()) 
       { 
        dbCommand.CommandText = "RBM_V1_GetTopLinks"; 

        dbCommand.Connection.Open(); 

        using(DbDataReader dbReader = dbCommand.ExecuteReader()) 
        { 
         if(dbReader.HasRows) 
         { 
          int intId = dbReader.GetOrdinal("id"); 
          int intText = dbReader.GetOrdinal("text"); 
          int intLink = dbReader.GetOrdinal("link"); 

          while(dbReader.Read()) 
          { 
           lLinks.Add(FillTopLinkDataRecord(dbReader, intId, intText, intLink)); 
          } 
         } 

         dbReader.Close(); 
        } 

        dbCommand.Connection.Close(); 
       } 
      } 
      catch(Exception ex) 
      { 
       lLinks = null; 
       SiteManager.Instance.LogError(ex); 
      } 

      return lLinks; 
     } 

:(

A connection was successfully established with the server, but then an error occurred during the pre-login handshake. (provider: SSL Provider, error: 0 - Not enough memory is available to complete this request) 

Source: .Net SqlClient Data Provider 

Method: Void OnError(System.Data.SqlClient.SqlException, Boolean) 

Stack Trace: at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection) 
    at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj) 
    at System.Data.SqlClient.TdsParser.ConsumePreLoginHandshake(Boolean encrypt, Boolean trustServerCert, Boolean& marsCapable) 
    at System.Data.SqlClient.TdsParser.Connect(ServerInfo serverInfo, SqlInternalConnectionTds connHandler, Boolean ignoreSniOpenTimeout, Int64 timerExpire, Boolean encrypt, Boolean trustServerCert, Boolean integratedSecurity, SqlConnection owningObject) 
    at System.Data.SqlClient.SqlInternalConnectionTds.AttemptOneLogin(ServerInfo serverInfo, String newPassword, Boolean ignoreSniOpenTimeout, Int64 timerExpire, SqlConnection owningObject) 
    at System.Data.SqlClient.SqlInternalConnectionTds.LoginNoFailover(String host, String newPassword, Boolean redirectedUserInstance, SqlConnection owningObject, SqlConnectionString connectionOptions, Int64 timerStart) 
    at System.Data.SqlClient.SqlInternalConnectionTds.OpenLoginEnlist(SqlConnection owningObject, SqlConnectionString connectionOptions, String newPassword, Boolean redirectedUserInstance) 
    at System.Data.SqlClient.SqlInternalConnectionTds..ctor(DbConnectionPoolIdentity identity, SqlConnectionString connectionOptions, Object providerInfo, String newPassword, SqlConnection owningObject, Boolean redirectedUserInstance) 
    at System.Data.SqlClient.SqlConnectionFactory.CreateConnection(DbConnectionOptions options, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection) 
    at System.Data.ProviderBase.DbConnectionFactory.CreatePooledConnection(DbConnection owningConnection, DbConnectionPool pool, DbConnectionOptions options) 
    at System.Data.ProviderBase.DbConnectionPool.CreateObject(DbConnection owningObject) 
    at System.Data.ProviderBase.DbConnectionPool.UserCreateRequest(DbConnection owningObject) 
    at System.Data.ProviderBase.DbConnectionPool.GetConnection(DbConnection owningObject) 
    at System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection owningConnection) 
    at System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory) 
    at System.Data.SqlClient.SqlConnection.Open() 
    at rbm.Portal.DAL.SiteManagerDB.GetTopLinks() 

GetTopLinks)は、以下のように定義されていますFillTopLinkDataRecordメソッドは、次のように定義されます。

private static Link FillTopLinkDataRecord(IDataRecord drLink, int intId, int intText, int intLink) 
     { 
      Link lLink = new Link(); 

      if(!drLink.IsDBNull(intId)) 
      { 
       lLink.Id = drLink.GetInt32(intId); 
      } 

      if(!drLink.IsDBNull(intText)) 
      { 
       lLink.Text = drLink.GetString(intText); 
      } 

      if(!drLink.IsDBNull(intLink)) 
      { 
       lLink.Url = drLink.GetString(intLink); 
      } 

      return lLink; 
     } 

CreateCommand()は、次のように定義されます。 :

public static DbCommand CreateCommand() 
     { 
      DbConnection dbConnection = CreateConnection(); 

      DbCommand dbCommand = dbConnection.CreateCommand(); 
      dbCommand.CommandType = CommandType.StoredProcedure; 

      return dbCommand; 
     } 

     public static DbConnection CreateConnection() 
     { 
      DbProviderFactory dbFactory = DbProviderFactories.GetFactory(RbmConfiguration.DbProvideName); 

      DbConnection dbConnection = dbFactory.CreateConnection(); 
      dbConnection.ConnectionString = RbmConfiguration.DbConnectionString; 

      return dbConnection; 
     } 

GetTopLinksは、このコードから呼び出されます。多くの

try 
       { 
        if(HttpContext.Current.Cache["TopLinks"] == null) 
        { 
         HttpContext.Current.Cache.Insert("TopLinks", SiteDB.GetTopLinks() ?? new List<Link>(), null, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration); 
        } 

        return ((List<Link>)HttpContext.Current.Cache["TopLinks"]); 
       } 
       catch(Exception ex) 
       { 
        SiteManager.Instance.LogError(ex); 
        return null; 
       } 

何もこのコードで変わっていない、それはSQLサーバーからデータを読み取り、サイトのメニューを構築します。

SQLボックスが問題であると仮定してエラーが発生した場合、IISボックスのIISRESETが約24時間問題を解決しているように見えます。 SQLボックスはW2K8R2(64ビット)であり、8コア(2.99GHz)、8GB RAM、多くの空き容量(250+ GB)を持っています。 IISボックスはW2K8R2(64ビット)であり、8コア(2.66GHz)、4GB RAM、多くの空きスペース(16 GB)を備えています。

誰もこの問題を以前に見たことがありますか? SQLまたはIISに問題がありますか?どんな助けもありがとう。

答えて

1

私にはいくつかの問題があります。

まず、あなたの接続をどこで処分しているのか分かりません。これはおそらくここでの主な問題であり、IISRESETが一時的に問題を解決する理由です。

接続は最終的にリサイクルされますが、負荷が十分に高い場合(それが非常に高くなる必要はない場合)、プールのメモリが不足します。

第2に、私はCreateCommandとCreateConnectionを抽象化するような数多くの開発者を知っていますが、長期的に機能するような方法では実装されていません。私がやる最初のことは、とにかく始まるコードの単なる行であるので、これらのメソッドを取り除くことです。

FYI先週、ほぼ同じコードレイアウトを使用したサイトを修正しました。サイトを使用している30人の人がいろいろなエラーで壊れていました。すべての汎用コマンドと接続のインスタンスを取り除き、ステートメントを使用してデータ呼び出しを適切に囲むと、エラーはなくなり、現在その100倍の数を簡単にサポートします。

+0

クリス、迅速な対応に感謝します。あなたは接続がクローズアウトされているのを見ることはできませんが、コマンドはusingでラップされており、dbCommand.Connection.Close()で明示的に閉じられています。それで足りないの?このアプリケーションにはたくさんのDBコードがないことを踏まえて、私はCreateCommandメソッドとCreateConnectionメソッドを提案どおりに修正します。一般的なものがまた問題を引き起こす可能性があることを知っておもしろい。 – markpirvine

+0

@markpirvine:私は間違いました。接続も同様に処理する必要があります。 – NotMe

+0

@markpirvine:IDisposableを実装するものは、Using節にラップするか、オブジェクトを適切に処分するtry..finallyを持つ必要があります。クラスはアンマネージコードのラッパーであるため、通常のガベージコレクションではこれらのリソースについて何もできません。 – NotMe