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 using System;
02 using System.Collections.Generic;
03 using System.Linq;
04 using System.Text;
05 using System.Threading;
06   
07 namespace Test1
08 {
09     sealed class SQLPool
10     {
11         //互斥锁
12         public static Mutex mutexSQLPool = new Mutex();
13   
14         //SQL池
15         Stack<string> pool;
16   
17         /// <summary>
18         /// 初始化SQL池
19         /// </summary>
20         internal SQLPool()
21         {
22             this.pool = new Stack<string>();
23         }
24   
25   
26         /// <summary>
27         /// 获取SQL池数量
28         /// </summary>
29         internal Int32 Count
30         {
31             get { return this.pool.Count; }
32         }
33   
34   
35         /// <summary>
36         /// 从池中取出SQL
37         /// </summary>
38         /// <returns></returns>
39         internal string Pop()
40         {
41             lock (this.pool)
42             {
43                 return this.pool.Pop();
44             }
45         }
46   
47   
48         /// <summary>
49         /// 增加一个SQL到池中
50         /// </summary>
51         /// <param name="item"></param>
52         internal void Push(string item)
53         {
54             if (item.Trim() == "")
55             {
56                 throw new ArgumentNullException("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         internal string[] Clear()
77         {
78             string[] array = new string[] { };
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             return array;
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 using System;
02 using System.Collections.Generic;
03 using System.Linq;
04 using System.Text;
05   
06 namespace Test1
07 {
08     class SQLPoolManage
09     {
10         //单例模型
11         public static readonly SQLPoolManage sqlPoolManage = new SQLPoolManage();
12   
13         #region 属性
14         SQLPool poolOfSQL;
15         #endregion
16   
17   
18         #region 构造函数
19         /// <summary>
20         /// 初始化
21         /// </summary>
22         public SQLPoolManage()
23         {
24             this.poolOfSQL = new SQLPool();
25         }
26         #endregion
27   
28   
29         #region 方法
30         /// <summary>
31         /// 将SQL语句加入SQL池中
32         /// </summary>
33         /// <param name="strSQL"></param>
34         public void PushSQL(string strSQL)
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         public void ExecuteSQL(object obj)
46         {
47             if (this.poolOfSQL.Count > 0)
48             {
49                 string[] array = this.poolOfSQL.Clear();
50                 //遍历array,执行SQL
51                 for (int i = 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执行线程

  总结有以下三种方法,具体请参见http://www.cnblogs.com/tianzhiliang/archive/2010/08/31/1813928.html

方法一:调用线程执行方法,在方法中实现死循环,每个循环Sleep设定时间;

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

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

  代码如下:

 

01 using System;
02 using System.Collections.Generic;
03 using System.Linq;
04 using System.Text;
05   
06 using System.Threading;
07   
08 namespace Test1
09 {
10   
11     class Program
12     {
13         static void Main(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 = new System.Threading.Timer(new System.Threading.TimerCallback(SQLPoolManage.sqlPoolManage.ExecuteSQL), null, 0, 100);
20   
21             Console.ReadLine();
22         }
23     }
24 }
posted @ 2011-09-05 15:59  TMajier  阅读(185)  评论(0编辑  收藏  举报