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

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

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

c#实现用SQL池(多线程),定时批量执行SQL语句的更多相关文章

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

    在实际项目开发中,业务逻辑层的处理速度往往很快,特别是在开发Socket通信服务的时候,网络传输很快,但是一旦加上数据库操作,性能一落千丈,数据库操作的效率往往成为一个系统整体性能的瓶颈.面对这问题, ...

  2. SQL Server自动化运维系列——批量执行SQL脚本(Power Shell)

    需求描述 一般在生产环境中,在投产的情况下,需要批量的来执行SQL脚本文件,来完成整个投产,如果投产文件比较多的情况下,无疑这是一个比较痛苦的过程,所以本篇通过PowerShell脚本来批量完成. 监 ...

  3. Jmeter(三十八)Jmeter Question 之 ‘批量执行SQL语句’

    知识使我们变得玩世不恭,智慧使我们变得冷酷无情,我们思考的太多,感知太少,除了机器,我们更需要人性,除了智慧,我们需要仁慈和善良. ------出自查理卓别林的演讲 前面有提到Jmeter使用JDBC ...

  4. PL/SQL中批量执行SQL脚本(不可把所有的语句都复制到New SQL Windows)

    PL/SQL中批量执行SQL脚本,不可把所有的语句都复制到New SQL Window,因为这样会导致缓冲区过大而进程卡死! 最好的办法是将要执行的SQL脚本存放到指定文件中,如C:\insert.s ...

  5. SQL*PLUS中批量执行SQL语句

    SQL*PLUS中批量执行SQL语句 今天由于工作的需要,要在CMD中批量执行大量的SQL语句,对于Oracle学习还处在入门阶段的我,只能硬着头皮到处去寻找资料(主要是网络资料,也包括自己的电子书) ...

  6. 批量执行sql语句

    基本使用 $sqls="sql语句1;sql语句2;sql语句n"; 或 $sqls="insert into xx;";  $sqls.="inse ...

  7. 批量执行SQL文件

    原文:批量执行SQL文件 摘要:很多时候我们在做系统升级时需要将大量的.sql文件挨个执行,十分不方便.而且考虑到执行顺序和客服的操作方便性,能不能找到一种简单的方法来批量执行这些sql文件呢? 主要 ...

  8. jdbc批量执行SQL insert 操作

    package com.file; import java.io.BufferedReader; import java.io.FileReader; import java.util.ArrayLi ...

  9. PHP mysqli 增强 批量执行sql 语句的实现代码

    本篇文章介绍了,在PHP中 mysqli 增强 批量执行sql 语句的实现代码.需要的朋友参考下. mysqli 增强-批量执行sql 语句 <?php //mysqli 增强-批量执行sql ...

随机推荐

  1. JQuery巧妙利用CSS操作打印样式

    一.添加打印样式 1. 为屏幕显示和打印分别准备一个css文件,如下所示:  用于屏幕显示的css: <link rel="stylesheet" href="cs ...

  2. ElementUI的提示框的使用记录

    1.popover点击之后隐藏 问题描述:做了一个通知面板功能,下面提示信息有路由,每次点击消息呢,就跳转到了路由页面,但是此时这个面板没关闭,希望将其关闭 解决:官方文档有个属性 <div&g ...

  3. Pinger

    import java.io.IOException;import java.io.InputStreamReader;import java.io.LineNumberReader;import j ...

  4. C#.NET常见问题(FAQ)-如何生成release版本的程序,生成debug版本的程序

    除了右击项目在生成中配置改成Release还要在顶部切换成Release     更多教学视频和资料下载,欢迎关注以下信息: 我的优酷空间: http://i.youku.com/acetaohai1 ...

  5. C#.NET常见问题(FAQ)-如何批量增加或取消注释

    选中一批文本之后 批量增加注释:Ctrl+K Ctrl+C 批量取消注释:Ctrl+K Ctrl+U     更多教学视频和资料下载,欢迎关注以下信息: 我的优酷空间: http://i.youku. ...

  6. 【CSWS2014 Summer School】互联网广告中的匹配和排序算法-蒋龙(下)

    [CSWS2014 Summer School]互联网广告中的匹配和排序算法-蒋龙(上) Fig19,用到了矩阵,这个我没有听太明白,蒋博士也没有详细说明.不过可以明确的一点就是,我们常说的K-mea ...

  7. Android Developers:日历提供者

    <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="ht ...

  8. 关于Haxe3新特性“内联构造方法”的解释

    学习过C/C++的童鞋们应该了解inline即内联机制的意义,Haxe语言也很好的支持内联机制,让开发者可以自己在空间效率和时间效率上进行取舍. 从Haxe3开始,构造方法也可以使用inline关键字 ...

  9. PHP採集利器:依据開始字符串和结束字符串截取须要的採集内容数据

    PHP採集利器:依据開始字符串和结束字符串截取须要的採集内容数据 function strCutByStr(&$str, $findStart, $findEnd = false, $enco ...

  10. 解决win10 获取不到ip

    1.检查Dhcp服务是否启动 2.关闭防火墙