SqlServer數據庫連接池溢出問題解決


今天解決了一個大Bug——數據庫連接池溢出問題,問題在於,DAL層的DbHelper類中的ExecuteReader()方法創建了大量未及時關閉的SqlConnection,致使網站在小規模負載壓力下崩潰。

當初的DbHelper類是根據網上給出的參考設計(51aspx.net)的,沒想到這個例子也有漏洞,源代碼如下:

        public static SqlDataReader ExecuteReader(String sqlText)
        {
            SqlCommand cmd = new SqlCommand();
            SqlConnection conn = new SqlConnection(ConnectionString);
            try
            {
                conn.Open();
                cmd.Connection = conn;
                cmd.CommandText = sqlText;
                SqlDataReader reader = cmd.ExecuteReader();
                return reader;
            }
            catch (Exception e)
            {
                conn.Close();
                throw e;
                return null;
            }
        }

這樣做的好處是:BLL與DAL只依靠sqlstring耦合,BLL中數據庫操作的語句更少。但是,以上代碼並沒有及時關閉創建的數據庫連接

修改如下:

        public static SqlDataReader ExecuteReader(String sqlText, SqlConnection conn)
        {
            SqlCommand cmd = new SqlCommand();
            try
            {
                conn.Open();
                cmd.Connection = conn;
                cmd.CommandText = sqlText;
                SqlDataReader reader = cmd.ExecuteReader();
                return reader;
            }
            catch (Exception e)
            {
                
                conn.Close();
                throw e;
               // return null;
            }
        }

BLL層使用代碼(語句已高亮):

       /// <summary>
        /// 獲得未回答的問題
        /// </summary>
        /// <param name="tagId">0表示獲取所有分類</param>
        /// <param name="pageNum"></param>
        /// <param name="totalPageNum"></param>
        /// <param name="queryType">0-default.aspx,1-list</param>
        /// <returns></returns>
        public List<Question> GetUnansweredQuestion(int tagId,int pageNum,ref int totalPageNum,int queryType)
        {
            List<Question> list = new List<Question>();
            String sql;
            if (queryType == 0)
                sql = "SELECT TOP 10 Question.* FROM [Question] WHERE replies = 0";
            else if(tagId>0)
                sql = String.Format("SELECT TOP {0} * FROM (SELECT Question.*,ROW_NUMBER() OVER (ORDER BY created DESC) AS RowNumber FROM [Question],[QuestionTagAssociation] WHERE Question.replies = 0 AND Question.qid = QuestionTagAssociation.qid AND QuestionTagAssociation.tid = {2}) A WHERE RowNumber > {0} * ({1}-1)", pageSize, pageNum, tagId);
            else
                sql = String.Format("SELECT TOP {0} * FROM (SELECT Question.*,ROW_NUMBER() OVER (ORDER BY created DESC) AS RowNumber FROM [Question] WHERE Question.replies = 0) A WHERE RowNumber > {0} * ({1}-1)", pageSize, pageNum);

            SqlConnection conn = DbHelper.getConnection(); SqlDataReader reader = DbHelper.ExecuteReader(sql, conn);
            fillQuestionList(list, reader);

            reader.Close(); conn.Close(); if (queryType != 0)
            {
                if(tagId>0)
                    sql = String.Format("SELECT count(*) FROM [Question],[QuestionTagAssociation] WHERE Question.replies = 0 AND Question.tid = QuestionTagAssociation.tid AND QuestionTagAssociation.tid = {0}", tagId);
                else
                    sql = "SELECT count(*) FROM [Question] WHERE Question.replies = 0";
                totalPageNum = (int)Math.Floor((double)DbHelper.getSingleInt(sql)/pageSize);
                
            }
    
            return list;
        }

修改后,系統在小規模負載壓力下正常運行。


免責聲明!

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



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