您的位置:知识库 » 数据库

【原创】c#实现用SQL池(多线程),定时批量执行SQL语句

作者: 田志良  来源: 博客园  发布时间: 2010-09-12 09:16  阅读: 2702 次  推荐: 0   原文链接   [收藏]  

  在实际项目开发中,业务逻辑层的处理速度往往很快,特别是在开发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
using System;<br>using System.Collections.Generic;<br>using System.Linq;<br>using System.Text;<br>using System.Threading;<br><br>namespace Test1<br>{<br>    sealed class SQLPool<br>    {<br>        //互斥锁<br>        public static Mutex mutexSQLPool = new Mutex();<br><br>        //SQL池<br>        Stack<string> pool;<br><br>        /// <summary><br>        /// 初始化SQL池<br>        /// </summary><br>        internal SQLPool()<br>        {<br>            this.pool = new Stack<string>();<br>        }<br><br><br>        /// <summary><br>        /// 获取SQL池数量<br>        /// </summary><br>        internal Int32 Count<br>        {<br>            get { return this.pool.Count; }<br>        }<br><br><br>        /// <summary><br>        /// 从池中取出SQL<br>        /// </summary><br>        /// <returns></returns><br>        internal string Pop()<br>        {<br>            lock (this.pool)<br>            {<br>                return this.pool.Pop();<br>            }<br>        }<br><br><br>        /// <summary><br>        /// 增加一个SQL到池中<br>        /// </summary><br>        /// <param name="item"></param><br>        internal void Push(string item)<br>        {<br>            if (item.Trim() == "")<br>            {<br>                throw new ArgumentNullException("Items added to a SQLPool cannot be null");<br>            }<br><br>            //此处向SQL池中push SQL必须与Clear互斥<br>            mutexSQLPool.WaitOne();<br>            try<br>            {<br>                this.pool.Push(item);    //此处如果出错,则不会执行ReleaseMutex,将会死锁<br>            }<br>            catch<br>            { <br>            }<br>            mutexSQLPool.ReleaseMutex();<br>        }<br><br><br>        /// <summary><br>        /// 清空SQL池<br>        /// 清空前,返回SQL池中所有SQL语句,<br>        /// </summary><br>        internal string[] Clear()<br>        {<br>            string[] array = new string[] { };<br><br>            //此处必须与Push互斥<br>            mutexSQLPool.WaitOne();<br>            try<br>            {<br>                array = this.pool.ToArray();     //此处如果出错,则不会执行ReleaseMutex,将会死锁<br>                this.pool.Clear();<br>            }<br>            catch<br>            { <br>            }<br>            mutexSQLPool.ReleaseMutex();<br><br>            return array;<br>        }<br>    }<br>}<br>

(二)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
using System;<br>using System.Collections.Generic;<br>using System.Linq;<br>using System.Text;<br><br>namespace Test1<br>{<br>    class SQLPoolManage<br>    {<br>        //单例模型<br>        public static readonly SQLPoolManage sqlPoolManage = new SQLPoolManage();<br><br>        #region 属性<br>        SQLPool poolOfSQL;<br>        #endregion<br><br><br>        #region 构造函数<br>        /// <summary><br>        /// 初始化<br>        /// </summary><br>        public SQLPoolManage()<br>        {<br>            this.poolOfSQL = new SQLPool();<br>        }<br>        #endregion<br><br><br>        #region 方法<br>        /// <summary><br>        /// 将SQL语句加入SQL池中<br>        /// </summary><br>        /// <param name="strSQL"></param><br>        public void PushSQL(string strSQL)<br>        {<br>            this.poolOfSQL.Push(strSQL);<br>        }<br><br><br>        /// <summary><br>        /// 每隔一段时间,触发ExecuteSQL<br>        /// ExecuteSQL用于执行SQL池中的SQL语句<br>        /// </summary><br>        /// <param name="obj"></param><br>        public void ExecuteSQL(object obj)<br>        {<br>            if (this.poolOfSQL.Count > 0)<br>            {<br>                string[] array = this.poolOfSQL.Clear();<br>                //遍历array,执行SQL<br>                for (int i = 0; i < array.Length; i++)<br>                {<br>                    if (array[i].ToString().Trim() != "")<br>                    {<br>                        try<br>                        {<br>                            //数据库操作<br>                            //......<br>                        }<br>                        catch<br>                        { <br>                        }<br>                    }<br>                }<br>            }<br>        }<br>        #endregion<br><br>    }<br>}<br>

(三)定时触发SQL执行线程

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

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

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

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

  代码如下:

1
using System;<br>using System.Collections.Generic;<br>using System.Linq;<br>using System.Text;<br><br>using System.Threading;<br><br>namespace Test1<br>{<br><br>    class Program<br>    {<br>        static void Main(string[] args)<br>        {<br>            //向SQL池中抛入SQL语句<br>            SQLPoolManage.sqlPoolManage.PushSQL("delete from tbl_test where id = 1");<br><br>            //定时触发SQL执行线程<br>            System.Threading.Timer threadTimer = new System.Threading.Timer(new System.Threading.TimerCallback(SQLPoolManage.sqlPoolManage.ExecuteSQL), null, 0, 100);<br><br>            Console.ReadLine();<br>        }<br>    }<br>}<br><br>
0
0

数据库热门文章

    数据库最新文章

      最新新闻

        热门新闻