开发者

ASP.NET SQL Server ConsumePreLoginHandshake Not enough memory Exception

I have a web site that has recently started throwing the following error:

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()

The GetTopLinks() is defined as:

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

The FillTopLinkDataRecord method is defined as:

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

The CreateCommand() is defined as:

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

The GetTopLinks is called from this code:

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

Nothing much has changed with this code, it reads data from the SQL server and builds a menu for the site.

I'm confused as to where the problem lies, from the error I would assume that the SQL box is the problem, however an IISRESET on the IIS box seems to fix the problem for approx 24 hours. The SQL box is W2K8R2 (64bit) and has 8 cores (2.99GHz), 8GB RAM and lots of free space (250+ GB). The IIS box is W2K8R2 (64bit) and has 8 cores (2.66GHz), 4GB RAM and lots of free space (16 GB).

Has anyone seen this problem before? Is the problem with SQL or IIS? Any help would be appreciated.


There are a couple issues I see.

First, I don't see where you are disposing of your connections. Which is probably the main issue here and why an IISRESET temporarily fixes the problem.

Connections will eventually get recycled, but if your load is high enough (and it doesn't have to be very high for this to break) then it's going to run out of memory for the pool.

Second, I know a number of dev's like to abstract away CreateCommand and CreateConnection, but I've never seen it implemented in a way that works long term. The first thing I would do is rip those methods out as they are just single lines of code to begin with anyway.

FYI last week I fixed a site that used nearly the exact same code layout. It was breaking with various errors with 30 people using the site. Once I got rid of all the generic command and connection instantiation and properly surrounded the data calls with using statements the errors went away and now easily supports 100 times that number.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜