• 实现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池代码:

    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池管理类代码:

    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;

      代码如下:

    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();
            }
        }
    }
    
    
  • 相关阅读:
    蓝桥杯 十六进制转八进制
    蓝桥杯 字母图形
    2017.12.13T19_B2_5mianshiti
    2017.11.21T19_B2_6.2讲义
    2017.12.13T19_B2_6zuoye
    2017.12.1T19_B2_5zuoye
    2017.12.1T19_B2_4zuoye
    2017.12.1T19_B2_4——2
    2017.12.1T19_B2_4.3kehouzuoye
    2017.12.1T19_B2_4.2
  • 原文地址:https://www.cnblogs.com/tianzhiliang/p/1823951.html
Copyright © 2020-2023  润新知