改進前分析:
由于之前做的項目占用sqlserver太多,程序運行時,導(dǎo)致sqlserver占用CPU 60%左右,內(nèi)存占用1.6G左右,這種情況下可能會導(dǎo)致服務(wù)器的宕機或其它軟件無法正常運行。而程序本身并沒有占用太多CPU和內(nèi)存。于是為減少sqlserver的占用,先后使用了兩個解決辦法:數(shù)據(jù)庫連接池和數(shù)據(jù)緩沖池。
由于是在多線程環(huán)境下,必須要保證數(shù)據(jù)同步。而本人對EF沒有深入研究,所以只好自己寫。
數(shù)據(jù)庫連接池思路:
1、當(dāng)前軟件中必須有且只有一個數(shù)據(jù)庫連接池,所以使用單例模式進行定義。
2、為方便調(diào)用,方法使用static定義。
4、調(diào)用DBConnPool(數(shù)據(jù)庫連接池)時,必須保證已經(jīng)初始化必要的字段,而本類是靜態(tài)類,所以使用靜態(tài)構(gòu)造方法,在靜態(tài)構(gòu)造方法中初始化必要的變量。
3、數(shù)據(jù)庫連接們(sqlconneciton s)必須存儲到一個字段中,這個字段是隨時增長的(在小于最大連接數(shù)時),所以我使用的是List<Sqlconnection>。
4、一個連接在同一時間只能由一個代碼調(diào)用,所以必須有屬性加以區(qū)分,所以封裝了自己的mySqlconn,里面包含兩個字段:sqlconnection 和bool IsUsed,當(dāng) 當(dāng)前連接正在使用時,IsUsed=true,使用完畢IsUsed=false;另外,一般在DBHelper中,我們習(xí)慣使用using將sqlconnection包括起來,以便達到手動后釋放的效果,這里有兩個解決方法:
4.1:mySqlconn實現(xiàn)IDsipose接口,在dispose中 ,將IsUsed設(shè)置為false;
4.2:不適用using,在sqlconnection使用完畢后,調(diào)用MySqlconn的Isused設(shè)置為false。本人使用的是這種方法。不過這兩種理論上都可以。
5、本程序中沒有用到事務(wù)處理,所以不對此進行設(shè)置,此思路和遠嗎也僅僅是針對當(dāng)前項目。
總結(jié):數(shù)據(jù)庫連接池整個的流程就是
1、調(diào)用DBConnPool(數(shù)據(jù)庫連接池)獲取一個數(shù)據(jù)庫連接。
2、如果是第一次調(diào)用則首先調(diào)用DBConnPool的靜態(tài)構(gòu)造函數(shù),對類進行初始化。
3、獲取數(shù)據(jù)庫連接
3.1、加鎖(線程間同步)
3.2、從List<MyConn>中獲取一個MyConn.IsUsed屬性為false的MyConn對象。如果沒有則返回Null
3.2、判斷返回的MyConn對象是否為null,如果為null,則判斷List<MyConn>.Count是否大于最大數(shù)據(jù)庫連接數(shù),如果大于,則sleep線程,并再次獲取,如果小于,則創(chuàng)建新的MyConn對象,并將其放入到List集合中。
3.3、將得到的MyConn對象的IsUsed設(shè)置為true。
3.4、解鎖
3.5、返回MyConn對象
4、MyConn對象使用完畢,設(shè)置MyConn.IsUsed為false。
貼上部分代碼:
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 }
下一次再寫多線程環(huán)境下數(shù)據(jù)緩沖池的