关于SQLSERVER数据库链接池

 


 

 

‘关于数据库链接池你们都据说过或者用过,但真正的了解有多少呢?sql

 

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

 

==============================================================================================================================数据库

首先说明一下测试环境:服务器

数据库版本: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.0spa

 

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

复制代码
    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.如何开启链接池?

只须要链接字符串中加入对应的选项便可:code

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";

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

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];
                }
            }
复制代码
相关文章
相关标签/搜索