在實際專案開發中,業務邏輯層的處理速度往往很快,特別是在開發Socket通訊服務的時候,網路傳輸很快,但是一旦加上資料庫操作,效能一落千丈,資料庫操作的效率往往成為一個系統整體效能的瓶頸。面對這問題,我們怎麼辦呢?好,下面我就為大家介紹一種方法:構建SQL池,分離業務邏輯層和資料訪問層,讓業務邏輯層從低效的資料庫操作解脫,以提高系統整體效能。
(一)SQL池
SQL池是SQL容器,用於存放業務邏輯層拋過來的SQL語句。SQL池主要提供以下幾種方法:
1)internal string Pop(),從池中取出SQL。
2)internal void Push(string item),增加一個SQL到池中。
3)internal string[] Clear(),清空SQL池,清空前,返回SQL池中所有SQL語句。
特別提醒一下,SQL池是面向多執行緒的,所以必須對公共資源SQL採取鎖機制。這裡採用互斥鎖,當業務邏輯層執行緒往SQL池中拋入SQL語句時,禁止SQL執行執行緒執行SQL語句,反之,當SQL執行執行緒執行SQL語句時,也不允許業務邏輯層執行緒往SQL池中拋入SQL語句。為什麼要這麼做?因為SQL執行執行緒是批量執行SQL語句,在批量執行SQL語句前,會從池中取出所有SQL語句,如果此時業務邏輯層執行緒往SQL池中拋入SQL語句,則會導致這些SQL語句丟失,得不到執行。
下面是SQL池程式碼:
02 |
using System.Collections.Generic; |
05 |
using System.Threading; |
12 |
public static Mutex mutexSQLPool = new Mutex(); |
22 |
this.pool = new Stack<string>(); |
31 |
get { return this.pool.Count; } |
43 |
return this.pool.Pop(); |
52 |
internal void Push(string item) |
54 |
if (item.Trim() == "") |
56 |
throw new ArgumentNullException("Items added to a SQLPool cannot be null"); |
59 |
//此處向SQL池中push SQL必須與Clear互斥 |
60 |
mutexSQLPool.WaitOne(); |
63 |
this.pool.Push(item); //此處如果出錯,則不會執行ReleaseMutex,將會死鎖 |
68 |
mutexSQLPool.ReleaseMutex(); |
74 |
/// 清空前,返回SQL池中所有SQL語句, |
76 |
internal string[] Clear() |
78 |
string[] array = new string[] { }; |
81 |
mutexSQLPool.WaitOne(); |
84 |
array = this.pool.ToArray(); //此處如果出錯,則不會執行ReleaseMutex,將會死鎖 |
90 |
mutexSQLPool.ReleaseMutex(); |
(二)SQL池管理
SQL池管理主要用於管理SQL池,向業務邏輯層執行緒和SQL執行執行緒提供介面。
業務邏輯層執行緒呼叫 public void PushSQL(string strSQL) 方法,用於向SQL池拋入SQL語句。
SQL執行執行緒呼叫 public void ExecuteSQL(object obj) 方法,用於批量執行SQL池中的SQL語句。
注意,SQL池管理類採用單例模型,為什麼要採用單例模型?因為SQL池只能存在一個例項,無論是業務邏輯層執行緒還是SQL執行執行緒,僅會操作這一個例項,否則,將會導致SQL池不唯一,SQL執行無效。
下面是SQL池管理類程式碼:
02 |
using System.Collections.Generic; |
11 |
public static readonly SQLPoolManage sqlPoolManage = new SQLPoolManage(); |
22 |
public SQLPoolManage() |
24 |
this.poolOfSQL = new SQLPool(); |
34 |
public void PushSQL(string strSQL) |
36 |
this.poolOfSQL.Push(strSQL); |
41 |
/// 每隔一段時間,觸發ExecuteSQL |
42 |
/// ExecuteSQL用於執行SQL池中的SQL語句 |
45 |
public void ExecuteSQL(object obj) |
47 |
if (this.poolOfSQL.Count > 0) |
49 |
string[] array = this.poolOfSQL.Clear(); |
51 |
for (int i = 0; i < array.Length; i++) |
53 |
if (array[i].ToString().Trim() != "") |
(三)定時觸發SQL執行執行緒
總結有以下三種方法,具體請參見http://www.cnblogs.com/tianzhiliang/archive/2010/08/31/1813928.html:
方法一:呼叫執行緒執行方法,在方法中實現死迴圈,每個迴圈Sleep設定時間;
方法二:使用System.Timers.Timer類;
方法三:使用System.Threading.Timer;
程式碼如下:
02 |
using System.Collections.Generic; |
06 |
using System.Threading; |
13 |
static void Main(string[] args) |
16 |
SQLPoolManage.sqlPoolManage.PushSQL("delete from tbl_test where id = 1"); |
19 |
System.Threading.Timer threadTimer = new System.Threading.Timer(new System.Threading.TimerCallback(SQLPoolManage.sqlPoolManage.ExecuteSQL), null, 0, 100); |
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12639172/viewspace-673724/,如需轉載,請註明出處,否則將追究法律責任。