非常老的话题 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的最大连接数

1 usingSystem;2 usingSystem.Collections.Generic;3 usingSystem.Linq;4 usingSystem.Text;5 usingSystem.Data;6 usingSystem.Data.SqlClient;7

8 namespaceSQLServerMaxConnectionTest9 {10 classProgram11 {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 collection = new List();17 for (int i = 0; i < maxCount; i++)18 {19 Console.WriteLine(string.Format("成功创建连接对象{0}",i));20 try

21 {22 var db = newSqlConnection(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:22System.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 usingSystem;2 usingSystem.Collections.Generic;3 usingSystem.Linq;4 usingSystem.Text;5 usingSystem.Data;6 usingSystem.Data.SqlClient;7

8 namespaceSQLServerMaxConnectionTest9 {10 classProgram11 {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 collection = new List();18 for (int i = 0; i < maxCount; i++)19 {20 Console.WriteLine(string.Format("成功创建连接对象{0}",i));21 try

22 {23 var db = newSqlConnection(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个长连接

java:java语言制定了连接数据库的标准JDBC,各种数据库只需要按JDBC规范实现相应的驱动程序,JAVA程序通过JDBC API访问不同类型数据库

pgsql的JDBC驱动完全由java实现,没有其他语言依赖库,类似于python标准数据库接口为python DB-API

python sqlserver api连接池_非常老的话题 SQLSERVER连接池相关推荐

  1. python 大智慧股池_跟我从零开始学会大智慧股票池自动交易

    自从上次发表关于自动交易系列教程后,很多朋友对自动交易产生了极大兴趣,然而还有很多朋友因为没接触过股票池和自动交易,相对比较陌生,希望我能从更简单详细的角度来让刚接触的朋友更快的掌握股票自动交易的方法 ...

  2. [并发并行]_[线程池]_[Programming With POSIX Threads的线程池实现分析1]

    场景 1.C++标准库没有提供线程池操作, 连Win32都没有集成线程池, 相比之下macOS完善多了, 至少有operations. 多线程在执行多任务时有很大优势, 比如同时管理多个设备, 多个s ...

  3. 博途plc连接电脑_西门子CP2431通过SIMATIC NET连接WinCC

    CP243-1作为S7-200的以太网模块,除IT功能外,只支持西门子私有的S7协议,理论上只能通过OPC的方式和上位机组态软件通信,OPC服务器可以是S7-200专用的PC ACCESS软件,也可以 ...

  4. 运行时常量池_从String的intern()到常量池

    前言 在知乎上遇到一个刚学Java就接触的字符串比较的问题: 通常,根据"==比较的是地址,equals比较的是值"介个定理就能得到结果.但是String有些特殊,通过new St ...

  5. java如何关闭线程池_如何优雅的关闭Java线程池

    ⾯试中经常会问到,创建⼀个线程池需要哪些参数.线程池的工作原理,却很少会问到线程池如何安全关闭的. 也正是因为⼤家不是很关注这块,即便是⼯作三四年的⼈,也会有因为线程池关闭不合理,导致应用⽆法正常st ...

  6. 项目使用线程池_并发编程系列1:线程池的架构实现、大小配置、及四种线程池使用...

    △ 公众号回复关键词"架构" 即可领取<1500+BAT架构及面试专题合集> 本篇为线程池系列文章之一,不经常使用线程池的童鞋,还有对几种线程的使用不甚了解的童鞋,可以 ...

  7. 连接超时_记一次网络请求连接超时的事故

    点击上方蓝色字关注我们~前言 从HTTP请求超时.重试机制.操作系统网络等层面剖析了事故的原因,最终解决业务问题. 这里先抛两个问题: 1)你遭遇过由于网络连接或请求超时造成的生产事故吗? 2)你知道 ...

  8. 兄弟1218无线打印服务器错误,兄弟hl-1218w打印机无线连接方法_兄弟hl-1218w打印机无线怎么连接-硬件之家...

    兄弟hl-1218w打印机无线怎么连接呢?想要我们的机器正常工作且发挥最大功效,连接网络是必然的.可是具体该如何操作呢?想必还有很多的小伙伴还不会整呢吧!今日小编就来为大家介绍一下详细的操作流程,一起 ...

  9. db2 jdbc 连接池_【转】java jdbc连接db2

    /**了解基础情况**/ 对于Java程序员而言,DB2 提供了两种应用程序编程接口(API):JDBC 和 SQLJ. JDBC: JDBC 驱动程序分为旧的/CLI 驱动程序和新的通用 JDBC ...

最新文章

  1. Remoting简介
  2. zShowBox (图片放大展示jquery版 兼容性好)
  3. neo4jd3的使用流程(转载)
  4. 系统之家win11最新旗舰版64位镜像v2021.07
  5. Spring MVC国际化(i18n)和本地化(L10n)示例
  6. 前端开发要注意的浏览器兼容性问题整理
  7. laravel 中间件中返回视图
  8. 阿里巴巴fastjson @JSONField 注解说明
  9. SQL大圣之路笔记——SQL 行转列,列转行
  10. Atitit 项目范围管理 目录 1. 应该包含下面过程:启动、范围计划、范围定义、范围核实及范围变更控制 1 1.1. 项目范围管理的五个过程 1 2. 启动过程 1 2.1. 项目章程(如质量、
  11. 昆仑通态复制的程序可以用吗_昆仑通态专题(九):MCGS组态软件的实时数据库...
  12. jquery将html转换word,将网页内容导出word文档jQuery插件
  13. 学习计算机组装与维护的意义,计算机组装与维护课程学习体会
  14. 微信指纹支付原理浅析
  15. Flutter ListView ListView.build ListView.separated
  16. SpringSecurity实战(五)-认证流程源码分析
  17. 内嵌PDF网页无法打开的解决办法
  18. Java生成条形码图片,并保存在指定路径
  19. mysql 关联更新_MySQL UPDATE多表关联更新
  20. STC8A8K64单片机关于AT24C04基本读写操作(包含硬件I2C与软件模拟I2C)

热门文章

  1. 通过js判断不同终端类型,跳转到不同的页面
  2. php二进制安全的含义
  3. 如何正确的使用单例模式
  4. 从godaddy转出域名
  5. Python+OpenCV图像处理(十五)—— 圆检测
  6. 【前端】.easyUI.c#
  7. pcm 转化为wav 文件
  8. ActiveMQ 部署及发送接收消息
  9. 安卓飞机大战(三) 弹出对话框
  10. CentOS7 下DNS的搭建