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池代碼:

 

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

 

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

 

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

 

 

(三)定時觸發SQL執行線程

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

方法一:調用線程執行方法,在方法中實現死循環,每個循環Sleep設定時間;

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

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

  代碼如下:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
using  System;
using  System.Collections.Generic;
using  System.Linq;
using  System.Text;
  
using  System.Threading;
  
namespace  Test1
{
  
     class  Program
     {
         static  void  Main( string [] args)
         {
             //向SQL池中拋入SQL語句
             SQLPoolManage.sqlPoolManage.PushSQL( "delete from tbl_test where id = 1" );
  
             //定時觸發SQL執行線程
             System.Threading.Timer threadTimer = new  System.Threading.Timer( new  System.Threading.TimerCallback(SQLPoolManage.sqlPoolManage.ExecuteSQL), null , 0, 100);
  
             Console.ReadLine();
         }
     }
}


免責聲明!

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



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