在實際項目開發中,業務邏輯層的處理速度往往很快,特別是在開發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();
}
}
}
|
