1. 程式人生 > >c#實現用SQL池(多執行緒),定時批量執行SQL語句 (轉)

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

在實際專案開發中,業務邏輯層的處理速度往往很快,特別是在開發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 usingSystem;
02 usingSystem.Collections.Generic;
03 usingSystem.Linq;
04 usingSystem.Text;
05 usingSystem.Threading;
06
07 namespaceTest1
08 {
09 sealedclassSQLPool
10 {
11 //互斥鎖
12 publicstaticMutex mutexSQLPool =newMutex();
13
14 //SQL池
15 Stack<string> pool;
16
17 /// <summary>
18 /// 初始化SQL池
19 /// </summary>
20 internalSQLPool()
21 {
22 this.pool =newStack<string>();
23 }
24
25
26 /// <summary>
27 /// 獲取SQL池數量
28 /// </summary>
29 internalInt32 Count
30 {
31 get{returnthis.pool.Count; }
32 }
33
34
35 /// <summary>
36 /// 從池中取出SQL
37 /// </summary>
38 /// <returns></returns>
39 internalstringPop()
40 {
41 lock(this.pool)
42 {
43 returnthis.pool.Pop();
44 }
45 }
46
47
48 /// <summary>
49 /// 增加一個SQL到池中
50 /// </summary>
51 /// <param name="item"></param>
52 internalvoidPush(stringitem)
53 {
54 if(item.Trim() =="")
55 {
56 thrownewArgumentNullException("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 /// <summary>
73 /// 清空SQL池
74 /// 清空前,返回SQL池中所有SQL語句,
75 /// </summary>
76 internalstring[] Clear()
77 {
78 string[] array =newstring[] { };
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 returnarray;
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 usingSystem;
02 usingSystem.Collections.Generic;
03 usingSystem.Linq;
04 usingSystem.Text;
05
06 namespaceTest1
07 {
08 classSQLPoolManage
09 {
10 //單例模型
11 publicstaticreadonlySQLPoolManage sqlPoolManage =newSQLPoolManage();
12
13 #region 屬性
14 SQLPool poolOfSQL;
15 #endregion
16
17
18 #region 建構函式
19 /// <summary>
20 /// 初始化
21 /// </summary>
22 publicSQLPoolManage()
23 {
24 this.poolOfSQL =newSQLPool();
25 }
26 #endregion
27
28
29 #region 方法
30 /// <summary>
31 /// 將SQL語句加入SQL池中
32 /// </summary>
33 /// <param name="strSQL"></param>
34 publicvoidPushSQL(stringstrSQL)
35 {
36 this.poolOfSQL.Push(strSQL);
37 }
38
39
40 /// <summary>
41 /// 每隔一段時間,觸發ExecuteSQL
42 /// ExecuteSQL用於執行SQL池中的SQL語句
43 /// </summary>
44 /// <param name="obj"></param>
45 publicvoidExecuteSQL(objectobj)
46 {
47 if(this.poolOfSQL.Count > 0)
48 {
49 string[] array =this.poolOfSQL.Clear();
50 //遍歷array,執行SQL
51 for(inti = 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執行執行緒

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

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

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

  程式碼如下:

01 usingSystem;
02 usingSystem.Collections.Generic;
03 usingSystem.Linq;
04 usingSystem.Text;
05
06 usingSystem.Threading;
07
08 namespaceTest1
09 {
10
11 classProgram
12 {
13 staticvoidMain(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 =newSystem.Threading.Timer(newSystem.Threading.TimerCallback(SQLPoolManage.sqlPoolManage.ExecuteSQL),null, 0, 100);
20
21 Console.ReadLine();
22 }
23 }
24 }