在实际项目开发中,业务逻辑层的处理速度往往很快,特别是在开发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池代码:
| 02 |
using System.Collections.Generic; |
| 05 |
using System.Threading; |
| 12 |
public static Mutex mutexSQLPool = new Mutex(); |
| 22 |
this.pool = new Stack<string>(); |
| 31 |
get { return this.pool.Count; } |
| 43 |
return this.pool.Pop(); |
| 52 |
internal void Push(string item) |
| 54 |
if (item.Trim() == "") |
| 56 |
throw new ArgumentNullException("Items added to a SQLPool cannot be null"); |
| 59 |
//此处向SQL池中push SQL必须与Clear互斥 |
| 60 |
mutexSQLPool.WaitOne(); |
| 63 |
this.pool.Push(item); //此处如果出错,则不会执行ReleaseMutex,将会死锁 |
| 68 |
mutexSQLPool.ReleaseMutex(); |
| 74 |
/// 清空前,返回SQL池中所有SQL语句, |
| 76 |
internal string[] Clear() |
| 78 |
string[] array = new string[] { }; |
| 81 |
mutexSQLPool.WaitOne(); |
| 84 |
array = this.pool.ToArray(); //此处如果出错,则不会执行ReleaseMutex,将会死锁 |
| 90 |
mutexSQLPool.ReleaseMutex(); |
(二)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池管理类代码:
| 02 |
using System.Collections.Generic; |
| 11 |
public static readonly SQLPoolManage sqlPoolManage = new SQLPoolManage(); |
| 22 |
public SQLPoolManage() |
| 24 |
this.poolOfSQL = new SQLPool(); |
| 34 |
public void PushSQL(string strSQL) |
| 36 |
this.poolOfSQL.Push(strSQL); |
| 41 |
/// 每隔一段时间,触发ExecuteSQL |
| 42 |
/// ExecuteSQL用于执行SQL池中的SQL语句 |
| 45 |
public void ExecuteSQL(object obj) |
| 47 |
if (this.poolOfSQL.Count > 0) |
| 49 |
string[] array = this.poolOfSQL.Clear(); |
| 51 |
for (int i = 0; i < array.Length; i++) |
| 53 |
if (array[i].ToString().Trim() != "") |
(三)定时触发SQL执行线程
总结有以下三种方法,具体请参见http://www.cnblogs.com/tianzhiliang/archive/2010/08/31/1813928.html:
方法一:调用线程执行方法,在方法中实现死循环,每个循环Sleep设定时间;
方法二:使用System.Timers.Timer类;
方法三:使用System.Threading.Timer;
代码如下:
| 02 |
using System.Collections.Generic; |
| 06 |
using System.Threading; |
| 13 |
static void Main(string[] args) |
| 16 |
SQLPoolManage.sqlPoolManage.PushSQL("delete from tbl_test where id = 1"); |
| 19 |
System.Threading.Timer threadTimer = new System.Threading.Timer(new System.Threading.TimerCallback(SQLPoolManage.sqlPoolManage.ExecuteSQL), null, 0, 100); |
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/12639172/viewspace-673724/
,如需转载,请注明出处,否则将追究法律责任。