ADO.NET数据连接池剖析

来源:asp之家 时间:2023-06-27 17:23:29 

本篇文章起源于在GCR MVP Open Day的时候和C# MVP张响讨论连接池的概念而来的。因此单独写一篇文章剖析一下连接池。

为什么需要连接池
剖析一个技术第一个要问的是,这项技术为什么存在。
对于每一个到SQL Server的连接,都需要经历TCP/IP协议的三次握手,身份认证,在SQL Server里建立连接,分配资源等。而当客户端关闭连接时,客户端就会和SQL Server终止物理连接。但是,我们做过数据库开发的人都知道,每次操作完后关闭连接是再正常不过的事了,一个应用程序即使在负载不大的情况下也需要不停的连接SQL Server和关闭连接,同一个应用程序同时也可能存在多个连接。

因此,如果不断的这样建立和关闭连接,会是非常浪费资源的做法。因此Ado.net中存在连接池这种机制。在对SQL Server来说的客户端的应用程序进程中维护连接池。统一管理Ado.net和SQL Server的连接,既连接池保持和SQL Server的连接,当Connection.Open()时,仅仅从连接池中分配一个已经和SQL Server建立的连接,当Connection.Close()时,也并不是和SQL Server物理断开连接,仅仅是将连接进行回收。

因此,连接池总是能维护一定数量的和SQL Server的连接,以便应用程序反复使用这些连接以减少性能损耗。

重置连接的sys.sp_reset_connection
连接是有上下文的,比如说当前连接有未提交的事务,存在可用的游标,存在对应的临时表。因此为了便于连接重复使用,使得下一个连接不会收到上一个连接的影响,SQL Server通过sys.sp_reset_connection来清除当前连接的上下文,以便另一个连接继续使用。

当在Ado.net中调用了Connection.Close()时,会触发sys.sp_reset_connection。这个系统存储过程大概会做如下事情:
关闭游标
清除临时对象,比如临时表
释放锁
重置Set选项
重置统计信息
回滚未提交的事务
切换到连接的默认数据库
重置Trace Flag
此外,根据BOL上的信息:

代码如下:


"The sp_reset_connection stored procedure is used by SQL
Server to support remote stored procedure calls in a transaction. This stored
procedure also causes Audit Login and Audit Logout events to fire when a
connection is reused from a connection pool."


可以知道不能显式的在SQL Server中调用sys.sp_reset_connection,此外,这个方法还会触发Audit Login和Audit Logout事件。

一个简单的示例
下面我们通过一个简单的示例来看连接池的使用:
首先我分别使用四个连接,其中第一个和第二个连接之间有10秒的等待时间:

代码如下:


String ConnectionString = "data source=.\\sql2012;database=AdventureWorks;uid=sa;pwd=sasasa";
SqlConnection cn1=new SqlConnection(ConnectionString);
SqlCommand cmd1=cn1.CreateCommand();
cmd1.CommandText="SELECT * FROM dbo.ABCD";
cn1.Open();
cmd1.ExecuteReader();
cn1.Close();
Response.Write("连接关闭时间:"+DateTime.Now.ToLongTimeString()+"<br />");
System.Threading.Thread.Sleep(10000);
SqlConnection cn2=new SqlConnection(ConnectionString);
SqlCommand cmd2=cn2.CreateCommand();
cmd2.CommandText="SELECT * FROM dbo.ABCD";
cn2.Open();
cmd2.ExecuteReader();
cn2.Close();
Response.Write("连接关闭时间:"+DateTime.Now.ToLongTimeString()+"<br />");
SqlConnection cn3=new SqlConnection(ConnectionString);
SqlCommand cmd3=cn3.CreateCommand();
cmd3.CommandText="SELECT * FROM dbo.ABCD";
cn3.Open();
cmd3.ExecuteReader();
cn3.Close();
Response.Write("连接关闭时间:"+DateTime.Now.ToLongTimeString()+"<br />");
System.Threading.Thread.Sleep(1500);
SqlConnection cn4=new SqlConnection(ConnectionString);
SqlCommand cmd4=cn4.CreateCommand();
cmd4.CommandText="SELECT * FROM dbo.ABCD";
cn4.Open();
cmd4.ExecuteReader();
cn4.Close();
Response.Write("连接关闭时间:"+DateTime.Now.ToLongTimeString()+"<br />");


下面我们通过Profile截图:
ADO.NET数据连接池剖析    
我们首先可以看到,每一次Close()方法都会触发exec sp_reset_connection
此外,我们在中间等待的10秒还可以看到SP51是不断的,剩下几个连接全部用的是SPID51这个连接,虽然Ado.net Close了好几次,但实际上物理连接是没有中断的。
因此可以看出,连接池大大的提升了效率。

标签:ADO.NET,数据连接池
0
投稿

猜你喜欢

  • PHP实战之投票系统的实现

    2023-10-24 10:40:39
  • Golang多线程爬虫高效抓取大量数据的利器

    2024-02-20 06:24:44
  • python决策树之CART分类回归树详解

    2021-06-22 19:23:16
  • Python3 使用pip安装git并获取Yahoo金融数据的操作

    2023-11-17 21:56:48
  • Django对接elasticsearch实现全文检索的示例代码

    2023-07-02 01:31:29
  • 10款顶级jQuery插件推荐

    2011-08-14 07:55:39
  • python 爬取古诗文存入mysql数据库的方法

    2024-01-28 13:35:26
  • 一些文件未注册导致mssql表文件无法找开的解决方法

    2024-01-26 18:42:22
  • 自己写的一个PJBlog中可以双击输入验证码的修改

    2009-05-17 10:51:00
  • Python爬虫之Selenium实现键盘事件

    2022-08-28 03:40:37
  • 如何做一个计数器并让人家申请使用?

    2010-07-11 21:13:00
  • Oracle中执行动态SQL

    2024-01-19 20:55:37
  • python用线性回归预测股票价格的实现代码

    2023-01-24 02:14:31
  • MySQL 8.0新功能监控统计限制连接不再担心被垃圾SQL搞爆内存

    2024-01-16 12:51:25
  • 在pycharm中使用git版本管理以及同步github的方法

    2021-12-08 01:59:58
  • 网站改版常见问题答疑

    2008-08-22 18:31:00
  • 懒就要懒到底——鼠标自动点击(含时间判断)

    2024-04-22 22:18:06
  • python 服务器批处理得到PSSM矩阵的问题

    2021-05-19 12:21:13
  • python中列表(list)和元组(tuple)的深入讲解

    2021-08-18 01:39:02
  • Python读取键盘输入的2种方法

    2023-03-14 22:08:37
  • asp之家 网络编程 m.aspxhome.com