c#實現用SQL池(多執行緒),定時批量執行SQL語句 (轉)

iDotNetSpace發表於2010-09-13
在實際專案開發中,業務邏輯層的處理速度往往很快,特別是在開發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池程式碼:

 

01 using System;
02 using System.Collections.Generic;
03 using System.Linq;
04 using System.Text;
05 using System.Threading;
06   
07 namespace Test1
08 {
09     sealed class SQLPool
10     {
11         //互斥鎖
12         public static Mutex mutexSQLPool = new Mutex();
13   
14         //SQL池
15         Stack<string> pool;
16   
17         ///
18         /// 初始化SQL池
19         ///
20         internal SQLPool()
21         {
22             this.pool = new Stack<string>();
23         }
24   
25   
26         ///
27         /// 獲取SQL池數量
28         ///
29         internal Int32 Count
30         {
31             get { return this.pool.Count; }
32         }
33   
34   
35         ///
36         /// 從池中取出SQL
37         ///
38         ///
39         internal string Pop()
40         {
41             lock (this.pool)
42             {
43                 return this.pool.Pop();
44             }
45         }
46   
47   
48         ///
49         /// 增加一個SQL到池中
50         ///
51         ///
52         internal void Push(string item)
53         {
54             if (item.Trim() == "")
55             {
56                 throw new ArgumentNullException("Items added to a SQLPool cannot be null");
57             }
58   
59             //此處向SQL池中push SQL必須與Clear互斥
60             mutexSQLPool.WaitOne();
61             try
62             {
63                 this.pool.Push(item);    //此處如果出錯,則不會執行ReleaseMutex,將會死鎖
64             }
65             catch
66             { 
67             }
68             mutexSQLPool.ReleaseMutex();
69         }
70   
71   
72         ///
73         /// 清空SQL池
74         /// 清空前,返回SQL池中所有SQL語句,
75         ///
76         internal string[] Clear()
77         {
78             string[] array = new string[] { };
79   
80             //此處必須與Push互斥
81             mutexSQLPool.WaitOne();
82             try
83             {
84                 array = this.pool.ToArray();     //此處如果出錯,則不會執行ReleaseMutex,將會死鎖
85                 this.pool.Clear();
86             }
87             catch
88             { 
89             }
90             mutexSQLPool.ReleaseMutex();
91   
92             return array;
93         }
94     }
95 }

 

(二)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池管理類程式碼:

 

01 using System;
02 using System.Collections.Generic;
03 using System.Linq;
04 using System.Text;
05   
06 namespace Test1
07 {
08     class SQLPoolManage
09     {
10         //單例模型
11         public static readonly SQLPoolManage sqlPoolManage = new SQLPoolManage();
12   
13         #region 屬性
14         SQLPool poolOfSQL;
15         #endregion
16   
17   
18         #region 建構函式
19         ///
20         /// 初始化
21         ///
22         public SQLPoolManage()
23         {
24             this.poolOfSQL = new SQLPool();
25         }
26         #endregion
27   
28   
29         #region 方法
30         ///
31         /// 將SQL語句加入SQL池中
32         ///
33         ///
34         public void PushSQL(string strSQL)
35         {
36             this.poolOfSQL.Push(strSQL);
37         }
38   
39   
40         ///
41         /// 每隔一段時間,觸發ExecuteSQL
42         /// ExecuteSQL用於執行SQL池中的SQL語句
43         ///
44         ///
45         public void ExecuteSQL(object obj)
46         {
47             if (this.poolOfSQL.Count > 0)
48             {
49                 string[] array = this.poolOfSQL.Clear();
50                 //遍歷array,執行SQL
51                 for (int i = 0; i < array.Length; i++)
52                 {
53                     if (array[i].ToString().Trim() != "")
54                     {
55                         try
56                         {
57                             //資料庫操作
58                             //......
59                         }
60                         catch
61                         { 
62                         }
63                     }
64                 }
65             }
66         }
67         #endregion
68   
69     }
70 }

 

 

(三)定時觸發SQL執行執行緒

  總結有以下三種方法,具體請參見http://www.cnblogs.com/tianzhiliang/archive/2010/08/31/1813928.html

方法一:呼叫執行緒執行方法,在方法中實現死迴圈,每個迴圈Sleep設定時間;

方法二:使用System.Timers.Timer類;

方法三:使用System.Threading.Timer;

  程式碼如下:

 

01 using System;
02 using System.Collections.Generic;
03 using System.Linq;
04 using System.Text;
05   
06 using System.Threading;
07   
08 namespace Test1
09 {
10   
11     class Program
12     {
13         static void Main(string[] args)
14         {
15             //向SQL池中拋入SQL語句
16             SQLPoolManage.sqlPoolManage.PushSQL("delete from tbl_test where id = 1");
17   
18             //定時觸發SQL執行執行緒
19             System.Threading.Timer threadTimer = new System.Threading.Timer(new System.Threading.TimerCallback(SQLPoolManage.sqlPoolManage.ExecuteSQL), null, 0, 100);
20   
21             Console.ReadLine();
22         }
23     }
24 }

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12639172/viewspace-673724/,如需轉載,請註明出處,否則將追究法律責任。

相關文章