多線程環境下,手動創建數據庫連接池


改進前分析:

由於之前做的項目占用sqlserver太多,程序運行時,導致sqlserver占用CPU 60%左右,內存占用1.6G左右,這種情況下可能會導致服務器的宕機或其它軟件無法正常運行。而程序本身並沒有占用太多CPU和內存。於是為減少sqlserver的占用,先后使用了兩個解決辦法:數據庫連接池和數據緩沖池。

由於是在多線程環境下,必須要保證數據同步。而本人對EF沒有深入研究,所以只好自己寫。

數據庫連接池思路:

1、當前軟件中必須有且只有一個數據庫連接池,所以使用單例模式進行定義。

2、為方便調用,方法使用static定義。

4、調用DBConnPool(數據庫連接池)時,必須保證已經初始化必要的字段,而本類是靜態類,所以使用靜態構造方法,在靜態構造方法中初始化必要的變量。

3、數據庫連接們(sqlconneciton s)必須存儲到一個字段中,這個字段是隨時增長的(在小於最大連接數時),所以我使用的是List<Sqlconnection>。

4、一個連接在同一時間只能由一個代碼調用,所以必須有屬性加以區分,所以封裝了自己的mySqlconn,里面包含兩個字段:sqlconnection 和bool IsUsed,當 當前連接正在使用時,IsUsed=true,使用完畢IsUsed=false;另外,一般在DBHelper中,我們習慣使用using將sqlconnection包括起來,以便達到手動后釋放的效果,這里有兩個解決方法: 4.1:mySqlconn實現IDsipose接口,在dispose中 ,將IsUsed設置為false;

     4.2:不適用using,在sqlconnection使用完畢后,調用MySqlconn的Isused設置為false。本人使用的是這種方法。不過這兩種理論上都可以。

5、本程序中沒有用到事務處理,所以不對此進行設置,此思路和遠嗎也僅僅是針對當前項目。

總結:數據庫連接池整個的流程就是

  1、調用DBConnPool(數據庫連接池)獲取一個數據庫連接。

  2、如果是第一次調用則首先調用DBConnPool的靜態構造函數,對類進行初始化。

  3、獲取數據庫連接

    3.1、加鎖(線程間同步)

    3.2、從List<MyConn>中獲取一個MyConn.IsUsed屬性為false的MyConn對象。如果沒有則返回Null

    3.2、判斷返回的MyConn對象是否為null,如果為null,則判斷List<MyConn>.Count是否大於最大數據庫連接數,如果大於,則sleep線程,並再次獲取,如果小於,則創建新的MyConn對象,並將其放入到List集合中。

    3.3、將得到的MyConn對象的IsUsed設置為true。

    3.4、解鎖

    3.5、返回MyConn對象

  4、MyConn對象使用完畢,設置MyConn.IsUsed為false。

 

貼上部分代碼:

View Code
 1  public static MySqlConn GetConn()
 2         {
 3             MySqlConn conn = null;
 4 
 5             lock (syncget)
 6             {
 7                 if (listMySqlConn == null)
 8                 {
 9                     listMySqlConn = new List<MySqlConn>();
10                 }
11                 if (listMySqlConn.Count > 0)
12                 {
13                     conn = getConnFromCollection();
14 
15                     while (conn == null)
16                     {
17                         if (listMySqlConn.Count >= maxNum)
18                         {
19                             System.Threading.Thread.Sleep(200);
20                             conn = getConnFromCollection();
21                         }
22                         else
23                         {
24                             conn = new MySqlConn(listMySqlConn.Count, new SqlConnection(connstr));
25                             listMySqlConn.Add(conn);
26                         }
27                     }
28                 }
29                 else
30                 {
31                     conn = new MySqlConn(listMySqlConn.Count,new SqlConnection(connstr));
32                     listMySqlConn.Add(conn);
33                 }
34                 conn.IsUsed = true;
35                 if (conn.Sqlconn.State!=ConnectionState.Open)
36                 {
37                     conn.Sqlconn.Open();
38                 }
39             }
40             return conn;
41         }
42 
43         private static MySqlConn getConnFromCollection()
44         {
45             MySqlConn conn = null;
46             foreach (MySqlConn item in listMySqlConn)
47             {
48                 if (!item.IsUsed)
49                 {
50                     conn = item;
51                     break;
52                 }
53             }
54             return conn;
55         }

這個思路中沒有涉及數據庫連接池的關閉,由於本人這個項目是定時更新程序,每隔幾分鍾就要更新一次的,所以沒有設定。

不過可以提供一個思路,在MyConn中增加一個字段LastUseTime,記錄本連接上次使用時間。

在DBConnPool中定義一個System.Threading.Timer 變量,每隔2秒循環當前數據庫集合,如果發現當前項上次使用時間距離現在超過5分鍾,則將其銷毀。(如有更好方法,請告訴我,不勝感激..)

下一次再寫多線程環境下數據緩沖池的


免責聲明!

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



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