博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
c#实现用SQL池(多线程),定时批量执行SQL语句
阅读量:6147 次
发布时间:2019-06-21

本文共 4238 字,大约阅读时间需要 14 分钟。

在实际项目开发中,业务逻辑层的处理速度往往很快,特别是在开发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执行线程

  总结有以下三种方法,具体请参见:

方法一:调用线程执行方法,在方法中实现死循环,每个循环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();
        
}
    
}
}

转载地址:http://usmya.baihongyu.com/

你可能感兴趣的文章
Oracle中drop user和drop user cascade的区别
查看>>
登记申请汇总
查看>>
Office WORD如何取消开始工作右侧栏
查看>>
Android Jni调用浅述
查看>>
CodeCombat森林关卡Python代码
查看>>
第一个应用程序HelloWorld
查看>>
(二)Spring Boot 起步入门(翻译自Spring Boot官方教程文档)1.5.9.RELEASE
查看>>
Java并发编程73道面试题及答案
查看>>
企业级负载平衡简介(转)
查看>>
ICCV2017 论文浏览记录
查看>>
科技巨头的交通争夺战
查看>>
当中兴安卓手机遇上农行音频通用K宝 -- 卡在“正在通讯”,一直加载中
查看>>
Shell基础之-正则表达式
查看>>
JavaScript异步之Generator、async、await
查看>>
讲讲吸顶效果与react-sticky
查看>>
c++面向对象的一些问题1 0
查看>>
直播视频流技术名词
查看>>
IOC —— AOP
查看>>
比特币现金将出新招,推动比特币现金使用
查看>>
数据库的这些性能优化,你做了吗?
查看>>