非常老的话题 SQLSERVER连接池-阿里云开发者社区

开发者社区> 杰克.陈> 正文

非常老的话题 SQLSERVER连接池

简介: 原文:非常老的话题 SQLSERVER连接池 非常老的话题 SQLSERVER连接池 写这篇文章不是说要炒冷饭,因为园子里有非常非常多关于SQLSERVER连接池的文章,但是他们说的都是引用MSDN里的解释 或者自己做一些测试试验一下连接池的性能。
+关注继续查看
原文:非常老的话题 SQLSERVER连接池

非常老的话题 SQLSERVER连接池

写这篇文章不是说要炒冷饭,因为园子里有非常非常多关于SQLSERVER连接池的文章,但是他们说的都是引用MSDN里的解释

或者自己做一些测试试验一下连接池的性能。但是对于SQLSERVER连接池的内部机制,好像都没有非常清晰地说清楚。

 

连接池的作用就不说了,在园子里随便搜一大堆

还有使用连接池有利也有弊,大部分文章都说连接池的好处没有说连接池的不好的地方

连接池不好的地方在于事务的提交方面,如果上一个连接没有提交事务,有可能下一个

连接会遇到因为上一个连接的事务没有提交从而遇到意想不到的后果

详细的可以自行GOOGLE

先说一下带连接池功能的编程接口

微软的SQLSERVER客户端编程接口:

ADO和ADO.NET 都支持连接池这种机制

JAVA的JDBC也支持连接池这种机制

注意:连接池机制是客户端数据库驱动程序提供的,功能都在驱动程序里,所以JDBC跟ADO,ADO.NET的连接池功能会有区别

因为客户端应用程序都是通过加载SQLSERVER的数据驱动控件做SQLSERVER连接。目前客户端数据库驱动程序主要有3种:

1、MDAC(微软数据访问组件) SQL2000的时候开始有的

2、SQLSERVER Native Client SQL2005开始引入的

3、Microsoft JDBC Provider  使用机制与MDAC和SQLSERVER Native Client不同

 

下面再说一下在论坛里经常有人问到的问题:

问题1:SQLServer连接池被创建在SQLClient端还是SQLServer端?

 答案:在客户端

当应用程序运行的时候,会有一个连接池的管理控件运行在应用程序的进程里,统一管理应用程序和SQLSERVER建立的所有连接,

并且维护这些连接一直处于活动状态。当有用户发出一个connection open指令时连接池会在自己维护的连接池中找一个处于空闲状态

的连接放回自己管理的连接池里,给这个用户使用。当用户使用完毕后,发出connection close指令,连接池会把这个连接放回自己

管理的连接池里,让他重新处于空闲状态,而不是真的从SQL里登出。这样如果下次有用户需要相同连接,就可以重用这个连接,

而无须再去做物理连接了。就是说连接池是放在客户端的,是客户端机制

 

 

问题2:如果在一个应用程序里设置连接池的大小为40000个,第二个应用程序里设置连接池的大小也为40000个,

程序跟SQLSERVER会不会报错?

答案:不会

当应用程序运行的时候,会有一个连接池的管理控件运行在应用程序的进程里,统一管理应用程序和SQLSERVER建立的所有连接,

并且维护这些连接一直处于活动状态。当有用户发出一个connection open指令时连接池会在自己维护的连接池中找一个处于空闲状态

的连接放回自己管理的连接池里,给这个用户使用。当用户使用完毕后,发出connection close指令,连接池会把这个连接放回自己

管理的连接池里,让他重新处于空闲状态,而不是真的从SQL里登出。这样如果下次有用户需要相同连接,就可以重用这个连接,

而无须再去做物理连接了

这个问题是针对上面这段话的,如果一个应用程序指定了连接池的大小为40000个那么跟SQLSERVER的连接已经有40000个了,

SQLSERVER的最大连接数是32767,那么第二个应用程序再打开40000个连接会不会报错呢?

本人根据园子里的这篇文章做了一个实验测试会不会报错,修改了他里面的一些代码,下面是我自己写的代码跟报错的内容跟文章链接

做实验之前记得重启一下SQLSERVER

亲测SQLServer的最大连接数

http://www.cnblogs.com/wlb/archive/2012/04/08/2437617.html

 

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Data;
 6 using System.Data.SqlClient;
 7 
 8 namespace SQLServerMaxConnectionTest
 9 {
10     class Program
11     {
12         static void Main(string[] args)
13         {
14                int maxCount = 40000;
15                string connstr="Server=joe;Database=AdventureWorks;User ID=sa;Password=test;pooling=true;connection lifetime=0;min pool size = 1;max pool size=40000";
16                List<SqlConnection> collection = new List<SqlConnection>();
17              for (int i = 0; i < maxCount; i++)
18              {
19                  Console.WriteLine(string.Format("成功创建连接对象{0}",i));
20                  try
21                  {
22                      var db = new SqlConnection(connstr);
23                      db.Open();
24                      collection.Add(db);
25                  }
26                  catch (Exception ex)
27                  {
28                      WriteErrLog.AppendErrLog(ex.ToString());
29                  }
30                
31              }
32         }
33     }
34 }
1 2012-12-01 17:04:22 System.Data.SqlClient.SqlException: 当前命令发生了严重错误。应放弃任何可能产生的结果。
2    在 System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)
3    在 System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj)
4    在 System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
5    在 System.Data.SqlClient.SqlInternalConnectionTds.CompleteLogin(Boolean enlistOK)
6    在 System.Data.SqlClient.SqlInternalConnectionTds.AttemptOneLogin(ServerInfo serverInfo, String newPassword, Boolean ignoreSniOpenTimeout, Int64 timerExpire, SqlConnection owningObject)

 

由于本人的笔记本性能不给力,在cmd里面打开的对象数达到16531 另一个是16124的时候差不多死机了,所以未能截图。

16531+16124 差不多达到32767,测试结果表明,如果有程序一早打开了一定数目的连接,那么第二个应用程序就算

再打开40000个连接是没有用的并会报错,第二个应用程序能打开的连接数目等于SQLSERVER最大连接数减去第一个应用程序

打开的连接数

有一个问题非常奇怪:两个应用程序都可以指定连接池的最大连接数为40000,如果是这样的话应该SQLSERVER应该预先

保持了80000个活动连接,让应用程序连接进来,这样SQLSERVER应该会报错,但是我用下面代码测试了,发现没有报错

测试方法跟上面的那个测试一样,做下面实验之前请重启一下SQLSERVER

这个问题已经有答案了,答案在文章的结尾o(∩_∩)o

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Data;
 6 using System.Data.SqlClient;
 7 
 8 namespace SQLServerMaxConnectionTest
 9 {
10     class Program
11     {
12         static void Main(string[] args)
13         {
14                //改成500个连接
15                int maxCount = 500;
16                string connstr="Server=joe;Database=AdventureWorks;User ID=sa;Password=test;pooling=true;connection lifetime=0;min pool size = 1;max pool size=40000";
17                List<SqlConnection> collection = new List<SqlConnection>();
18              for (int i = 0; i < maxCount; i++)
19              {
20                  Console.WriteLine(string.Format("成功创建连接对象{0}",i));
21                  try
22                  {
23                      var db = new SqlConnection(connstr);
24                      db.Open();
25                      collection.Add(db);
26                  }
27                  catch (Exception ex)
28                  {
29                      WriteErrLog.AppendErrLog(ex.ToString());
30                  }
31                
32              }
33         }
34     }
35 }

希望高人可以解答一下

 

问题3:连接池字符串里要不要写pooling=true;connection lifetime=0;min pool size = 1;?

答案:个人觉得没有必要写,连接池默认是开启的,连接的生命周期没有必要指定,因为你都不知道

自己的SQL语句要运行多长时间,连接池的min pool size不需要指定了,只需要指定max pool size=32767

就可以了

 

问题4:sp_reset_connection 经常有人在论坛里问,使用SQL Trace的时候会有大量的sp_reset_connection

这个存储过程的执行,这个存储过程到底是什么来的?

网上对这个存储过程的资料很少,MSDN也找不到资料

答案:我们知道,每个连接都会维护自己的一些独有资源,比如临时表,变量,游标等,

他也有可能会修改一些默认的设置,例如事务隔离级别等。如果不同用户先后使用同一个连接,

会不会前一个用户设置的状态或申请的资源影响后一个用户正常使用呢?如果连接池的管理者

不做特殊处理,的确会有这种情况发生。所以微软的连接池技术里包括ADO.NET和ADO,

引入了一个特殊的指令:sp_reset_connection,来清除前一个用户做的绝大多数设置,避免这种问题。

sp_reset_connection会在SQLSERVER里做些什么?
1、清除连接现有所有内部数据结构。包括:
(1)清除所有openxml打开的document句柄
(2)关闭所有的游标(cursor)
(3)释放所有SQL语句句柄
(4)清除所有临时对象(临时表等)
(5)释放连接持有的所有锁
(6)清除缓存的所有安全上下文信息(security context)

 

2、重置连接设置。包括:
(1)重置连接的SQL Trace标志值(例如1204,1222,3604等)
(2)重置所有"SET" 选项值(SET IMPLICIT_TRANSACTIONS ON 等)
(3)重置连接的统计信息值


3、回滚所有SQLSERVER事务
需要说明的是,如果连接当前参与了一个由客户端发起的分布式事务,这个分布式事务不会受到影响。

在SQL里的事务还会被保留

 

4、把当前数据库切换到用户默认数据库

 

5、SQLSERVER会再次检查当前用户是否有权做数据库连接。如果这个权力已被移除
SQLSERVER会中断这个物理连接(这样防止一个已经被取消访问权的用户还能长时间
使用数据库的问题)

 

完成这些事情以后,一个连接基本上已经和他先前做的事情不再有任何关系(分布式事务除外)
可以说,这个连接和一个新的连接已经没有什么大的区别了。通过这些,应用程序的用户
可以尽快地拿到和释放连接,而SQLSERVER这边也不会因为连接的重复使用而产生相互影响的问题

 

准备下班了 有问题的童鞋可以发评论,希望大家拍砖o(∩_∩)o 

 

刚才测试了一下,在SSMS里运行下面语句

1 SELECT [program_name] ,[spid] FROM [sys].[sysprocesses] WHERE [spid]>50

然后运行上面我给出的示例代码程序跟SQLSERVER都在同一台电脑,改为500个连接那个,我双击打开了很多个cmd程序,

发现在cmd程序运行的时候会看到大量的连接在SSMS里面

 当那些cmd程序全部运行完毕之后,这些进程就在SQLSERVER里消失

 那么上面的问题:

两个应用程序都可以指定连接池的最大连接数为40000,如果是这样的话应该SQLSERVER应该预先

保持了80000个活动连接,让应用程序连接进来,这样SQLSERVER应该会报错

答案:应该是连接池保持了80000个活动连接,SQLSERVER并没有保持这些活动连接

想一想这也是正确的,如果客户端指定了80000个连接,SQLSERVER就要一次打开

80000个连接(实际数量是32767个)并对这些连接进行维护,那么SQLSERVER肯定

慢得要命。因为客户端的连接并没有达到80000个那么多,你在连接字符串里指定80000个

连接,实际上只是指定连接池的连接数

 

 

客户端的连接池和服务器端的线程池的区别

客户端连接池即使是40000个,也只是一个设定值,并不是说当前程序打开了40000个长连接

即使真的有40000个连接到SQL Server,SQL Server同一时刻也只能保持32767个长连接

 

 

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
阿里云服务器怎么设置密码?怎么停机?怎么重启服务器?
如果在创建实例时没有设置密码,或者密码丢失,您可以在控制台上重新设置实例的登录密码。本文仅描述如何在 ECS 管理控制台上修改实例登录密码。
9719 0
获取SQLSERVER2005 的连接字符串的另类方法
获取SQLSERVER2005 的连接字符串的另类方法,这个方法是我的一个很牛比的同事告诉我的。 很使用,而且很方面。 1 新建一个.txt文件 2 改名:aa.udl 或 aa.UDL   .后缀名为 udl . 3 双击 aa.udl     ------> 提供程序: 选择SQL Server版本:Micorsoft OLE DB Provider for SQL Server 4 下一步 :连接 (1)选择或输入服务器名称:写如你要连接的数据库服务器名称。
711 0
NAT网络部分客户端无法连接Server的解决方法
timestamp&recycle同时开启,引发的nat客户端访问异常的问题
3364 0
为Python安装pymssql模块来连接SQLServer
1、安装依赖包 yum install -y gcc python-devel 2、安装freetds 下载地址:http://pan.baidu.com/s/1pLKtFBl tar zxvf freetds-0.
971 0
无法打开到SQL Server的连接 (Microsoft SQL Server, 错误:53) .
标题: 连接到服务器 ------------------------------ 无法连接到 MSSQLSERVER。 ------------------------------ 其他信息: 在与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误。
2467 0
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,阿里云优惠总结大概有三种登录方式: 登录到ECS云服务器控制台 在ECS云服务器控制台用户可以更改密码、更换系.
13441 0
如何使用Oracle SQLDeveloper 中连接MS SQLServer和MySQL数据库
一、连接至MySQL数据库 1.下载mysql的jdbc驱动, http://dev.mysql.com/downloads/ 免费,嘿嘿。 2.解压zip文件(我下载的版本是mysql-connector-java-5.1.5),我们要用的是mysql-connector-java-5.1.5-bin.jar文件。
1051 0
asp.net 连接新浪微博
资料收集 1 官方 http://open.weibo.com/sdk/js http://open.weibo.com/widget/js#connect   2 教程 http://zzk.
714 0
+关注
杰克.陈
一个安静的程序猿~
10427
文章
2
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载