zoukankan      html  css  js  c++  java
  • 关于SQLSERVER数据库连接池

    ‘关于数据库连接池大家都听说过或者用过,但真正的了解有多少呢?

    • 数据连接池如何启用?有哪些主要的参数?
    • 为什么要使用连接池?
    • 如何关闭连接池?
    • 如何在不开启新的连接池情况下切换当前数据库?
    • 连接池的生命周期?
    • 当数据库服务器强制关闭连接时会怎么样?

    ==============================================================================================================================

    首先说明一下测试环境:

    数据库版本:SQL SERVER 12.0.2269.0 [Microsoft SQL Server 2014 Enterprise (64-bit)]

    C#版本: Microsoft Visual C# 2015 14.0.25431

    客户端版本:System.Data 4.0.0

    首先创建一个数据库访问类,便于测试:

        public class DbAccepter
        {
            /// <summary>
            /// 数据库连接
            /// </summary>
            private SqlConnection _conn = new SqlConnection();
    
            /// <summary>
            /// 数据库连接字符串
            /// </summary>
            private String _connectionString = "";
    
            /// <summary>
            /// 数据库连接字符串
            /// </summary>
            public string ConnectionString
            {
                get
                {
                    return _connectionString;
                }
    
                set
                {
                    _connectionString = value;
                    _conn.ConnectionString = _connectionString;
                }
            }
            
            public DataTable GetData(string sql)
            {
                string sss = _conn.State.ToString();
                using (SqlCommand cmd = new SqlCommand(sql, _conn))
                {
                    using (SqlDataAdapter adapter = new SqlDataAdapter(cmd))
                    {
                        DataSet ds = new DataSet();
                        _conn.Open();
                        adapter.Fill(ds);
                        _conn.Close();
                        return ds.Tables[0];
                    }
                }            
            }
        }

    1.如何开启连接池?

    只需要连接字符串中加入对应的选项即可:

    private static String _connectionString = "pooling=true;connection lifetime=5;min pool size = 2;max pool size=4; 
    Data Source = 127.0.0.1; Initial Catalog = tempdb; User ID = test; Password=Sm5lAXQiZ10L
    ";

    注意里面和连接池有关的参数:

    pooling=true; --表示开启连接池(默认为开启)

    min pool size = 2 --最小连接池大小:即什么也没执行初次连接的时候先和数据库服务建立n个连接

    max pool size=4 --最大连接池大小:允许建立的最大连接数,是在需要的时候建立。

    举例说明:min pool size = 2;max pool size=4 ; 

    点击按钮时调用以下代码执行数据库脚本。

     try
                {
                    info.Clear();
                    for (int i = 0; i < num.Value; i++)
                    {
                        Thread th = new Thread(GetCurrentDbName);
                        th.Start();
                    }
                }
                catch (Exception ex)
                {
                    listboxAdd(ex.Message);
                }

    这里的GetCurrentDbName方法是创建数据库连接然后执行一段SQL脚本,获取当前数据库的名称然后延时3S,所以每次执行SQL的时间都约为3秒

    select db_name();
    waitfor delay '00:00:03'; --延迟3秒

    这里我们先将并发数设为1,在初次建立连接时会创建2个连接。

    可以在数据库中进行查看:

    select * from sysprocesses where hostname='xxx' and loginame='test'

     

    2. 那连接池是和有什么有关呢?

    在同一个进程中,只和连接字符串有关,只要连接字符串一样就会使用同一个连接池。

     这里我们将连接字符串改为下图(只修改了最小数据池):

    执行指令后,再观察一下数据库的连接信息:

    我们发现会多出一个连接信息,可以会怀疑是不是使用的同个连接池。你可以将并发数改为4.

    可以看到,这时的连接数变为6,之前的连接字符串占用了两个,修改后的占用了4个。因为连接池的大小限制为4,所以说明确实是使用了两个连接池。

    当我们的并发请数大于最大连接池数会怎么样?这里我们修改一下之前的程序代码,记录线程调用方法执行的起止时间

    9个线程的执行截止时间,可以看出前四的截止时间基本相同,中间的四个大约比前4个晚3S。最后一个比中间四个晚3S。

    说明开始有4个线程的数据库请求获取到连接池资源,其它线程等待。

    这4个线程执行完成后,另4个线程获的连接池资源,最后一个线程等待真到再次释放连接池。

    那我们再看一下数据库的连接数仍然为4。说明有多个并行请求时,超过连接池的部分将等待。等待多久会超时呢???

    结论是如果想使用连接池,必须使用相同的连接字符串,必须一字不差(我并没有全部测试)。

    3.如何使用相同的连接池访问不同的数据库?

    在实际开发中我们会访问同一个服务器中的多个数据库,但又不想创建过多的连接。如果访问不同的库使用不同的连接字符串,那就会产生多个连接池。

    如这样:

    pooling=true;connection lifetime=10;min pool size = 2;max pool size=4; Data Source = 127.0.0.1; Initial Catalog = tempdb; User ID = test; Password=Sm5lAXQiZ10L
    
    pooling=true;connection lifetime=10;min pool size = 2;max pool size=4; Data Source = 127.0.0.1; Initial Catalog = master; User ID = test; Password=Sm5lAXQiZ10L

    这时有两个办法:

    1.在SQL语句中指定数据库名称(不太靠谱)

    2.不要重新创建连接,而是使用的相同的连接字符串创建连接后再切换数据库。实现代码如下:

      using (SqlCommand cmd = new SqlCommand(sql, _conn))
                {
                    using (SqlDataAdapter adapter = new SqlDataAdapter(cmd))
                    {
                        DataSet ds = new DataSet();
                        _conn.Open(); //这时指向的是tempdb
                        _conn.ChangeDatabase("master"); //切换数据库
                        adapter.Fill(ds);
                        _conn.Close();
                        return ds.Tables[0];
                    }
                }
  • 相关阅读:
    vb开发最全教程
    javascript javascript面向对象的理解及简单的示例
    javascript jquery封装对象时的错误,求解!我想知道为什么
    c# sql省市联动
    javascript javascript加载类似星座、血型的函数
    c# winform使用IrisSkin2换肤弹不出窗口解决方案
    access + vb + asp 遇到一些问题的总结
    ffmpeg windows下编译ffmpeg
    wffmpeg64.dll调用 尝试读取或写入受保护的内存。这通常指示其他内存已损坏。
    非托管 调用非托管资源的使用
  • 原文地址:https://www.cnblogs.com/champaign/p/6548325.html
Copyright © 2011-2022 走看看