Sql Server连接池及查看连接数相关 超时时间已到。超时时间已到,但是尚未从池中获取连接。出现这种情况可能是因为所有池连接均在使用,并且达到了最大池大小。

Asp.Net 连接池

数据库链接是一种危险的、昂贵的、有限的资源,特别是在多层Web应用程序中。你必须正确管理你的链接,因为你的方法将极大的影响应用程序的整体升级性。高性能应用程序与使用中的数据源保持最短时间的连接,并且利用性能增强技术,例如连接池。连接池用于ODBC 的 SQL Server、OLE DB 和 .NET 框架数据提供程序隐式缓冲连接。通过在连接字符串中指定不同的属性值,可以控制连接池的行为。

连接池概述

数据库链接池使应用程序能够重用池中的现有链接,而不是重复地建立对数据库的链接。这种技术将极大地增加应用程序的可扩展性,因为有限的数据库链接可以为很多的客户提供服务。此技术也将提高性能,因为能够避免用于建立新链接的巨大时间。
具体来说,大多数 ADO.NET 数据提供程序使用连接池,以提高围绕 Microsoft 断开连接的 .NET 结构构建的应用程序的性能。应用程序首先打开一个连接(或从连接池获得一个连接句柄),接着运行一个或多个查询,然后处理行集,最后将连接释放回连接池。如果没有连接池,这些应用程序将花费许多额外时间来打开和关闭连接。
下面将以SQL Server .NET Framework 数据提供程序连接池为例来说明连接池的一些性能和用法。(另外还有ODBC .NET Framework 数据提供程序连接池、OLE DB .NET Framework 数据提供程序连接池。)

池的创建和分配

当连接打开时,将根据一种精确的匹配算法来创建连接池,该算法会使连接池与连接中的字符串相关联。每个连接池都与一个不同的连接字符串相关联。当新连接打开时,如果连接字符串不精确匹配现有池,则将创建一个新池。
在以下示例中,将创建三个新的 SqlConnection 对象,但只需要使用两个连接池来管理这些对象。请注意,第一个和第二个连接字符串的差异在于为 Initial Catalog 分配的值。

  1. SqlConnection conn = new SqlConnection();
  2. conn.ConnectionString = "Integrated Security=SSPI;Initial Catalog=northwind";
  3. conn.Open();
  4. // Pool A is created.
  5. SqlConnection conn = new SqlConnection();
  6. conn.ConnectionString = "Integrated Security=SSPI;Initial Catalog=pubs";
  7. conn.Open();
  8. // Pool B is created because the connection strings differ.
  9. SqlConnection conn = new SqlConnection();
  10. conn.ConnectionString = "Integrated Security=SSPI;Initial Catalog=northwind";
  11. conn.Open();
  12. // The connection string matches pool A.

连接池一旦创建,直到活动进程终止时才会被毁坏。非活动或空池的维护只需要最少的系统开销。
在使用SQL Server .NET数据供应器链接池时,必须清楚:
链接是通过对链接字符串精确匹配的法则被池化的。池化机制对名称-值对间的空格敏感。例如,下面的两个链接字符串将生成单独的池,因为第二个字符串包含了一个额外的空字符。

  1. SqlConnection conn = new SqlConnection("Integrated Security=SSPI;Database=Northwind");
  2. conn.Open(); // Pool A is created
  3. SqlConmection conn = new SqlConnection("Integrated Security=SSPI ; Database=Northwind");
  4. conn.Open(); // Pool B is created (extra spaces in string)

连接的添加

连接池是为每个唯一的连接字符串创建的。当创建一个池后,将创建多个连接对象并将其添加到该池中,以满足最小池大小的要求。连接将根据需要添加到池中,直至达到最大池大小。
当请求 SqlConnection 对象时,如果存在可用的连接,则将从池中获取该对象。若要成为可用连接,该连接当前必须未被使用,具有匹配的事务上下文或者不与任何事务上下文相关联,并且具有与服务器的有效链接。
如果已达到最大池大小且不存在可用的连接,则该请求将会排队。当连接被释放回池中时,连接池管理程序通过重新分配连接来满足这些请求。对 Connection 调用 Close 或 Dispose 时,连接被释放回池中。

连接的移除

如果连接生存期已过期,或者连接池管理程序检测到与服务器的连接已断开,连接池管理程序将从池中移除该连接。请注意,只有在尝试与服务器进行通信后,才可以检测到这种情况。如果发现某连接不再连接到服务器,则会将其标记为无效。连接池管理程序会定期扫描连接池,查找已释放到池中并标记为无效的对象。找到后,这些连接将被永久移除。
如果存在与已消失的服务器的连接,那么即使连接池管理程序未检测到已断开的连接并将其标记为无效,仍有可能将此连接从池中取出。当发生这种情况时,将生成异常。但是,为了将该连接释放回池中,仍必须将其关闭。

选择池容量

能建立最大极限对于管理几千用户同时发出请求的大型系统来说是非常重要的。你需要监视链接池及应用程序的性能,以确定系统的最优池容量。最优容量还要依赖于运行SQL Server的硬件。
在开发期间,也许需要减小默认的最大池容量(目前是100)以帮助查找链接泄漏。
如果设立了最小池容量,那么当池最初被填充以达到该值时,会导致一些性能损失,尽管最初链接的几个客户会从中受益。注意,创建新链接的过程被序列化了,这就意味着当池最初被填充时,服务器无法处理同时发生的请求。

监视链接池化

要监视应用程序对链接池化的应用情况,可以使用随SQL Server发行的Profiler工具,或随微软Windows 2000发行的性能监视器。
要利用SQL Server Profiler 监视链接池化,操作如下:

  1. 单击开始,指向程序,指向Microsoft SQL Server,然后单击Profiler运行Profiler。
  2. 在文件菜单中,指向新建,然后单击跟踪。
  3. 提供链接内容,然后单击确定。
  4. 在跟踪属性对话框中,单击事件标签。
  5. 在已选事件类别列表中,确保审核登录和审核登出事件显示在安全审核下面。
  6. 单击运行开始跟踪。在链接建立时,将会看到审核登录事件;在链接关闭时看到审核登出事件。

要通过性能监视器监视链接池化,操作如下:

  1. 单击开始,指向程序,指向管理工具,然后单击性能运行性能监视器。
  2. 在图表背景中右击,然后单击增加计数器。
  3. 在性能对象下拉列表框中,单击SQL Server:通用统计。
  4. 在出现的列表中,单击用户链接。
  5. 单击增加,然后单击关闭。

在config中加pooling=false,说明程序中不用连接池。
现在,问题解决,在config文件的连接字符串中增加max pool size =”1000” 扩大连接池,同时,调整程序,尽量避免多开连接。

SQLSERVER连接池内部机制

Sql Server连接池及查看连接数相关 - 图1

查看连接数相关

获取SQL Server允许同时用户连接的最大数

  1. SELECT @@MAX_CONNECTIONS

获取当前指定数据库的连接信息

  1. SELECT * FROM master.dbo.sysprocesses WHERE dbid IN
  2. (
  3. SELECT dbid FROM master.dbo.sysdatabases
  4. WHERE NAME='YourDataBaseName'
  5. )
  6. --根据需要更改YourDataBaseName
  7. SELECT * FROM master.dbo.sysprocesses WHERE DB_NAME(dbid) = 'YourDataBaseName'
  8. SELECT db.name,* FROM master.dbo.sysprocesses pro
  9. inner join master.dbo.sysdatabases db on pro.dbid=db.dbid

获取当前SQL服务器所有的连接详细信息

  1. SELECT * FROM sysprocesses

以上查询结果包含了:系统进程和用户进程。
如果只是想查用户进程的话则需采用下面的方法

获取自上次启动 SQL Server服务 以来连接或试图连接的次数

  1. SELECT @@CONNECTIONS

查看当前数据库系统所有请求情况.
只列出了我认为比较重要有助于我解决问题的字段。

  1. SELECT ds.session_id,
  2. ds.status,
  3. Db_name(dr.database_id) AS database_name,
  4. ds.login_name,
  5. ds.login_time,
  6. ds.host_name,
  7. dc.client_net_address,
  8. dc.client_tcp_port,
  9. ds.program_name,
  10. dr.cpu_time,
  11. dr.reads,
  12. dr.writes,
  13. dc.num_reads,
  14. dc.num_writes,
  15. ds.client_interface_name,
  16. ds.last_request_start_time,
  17. ds.last_request_end_time,
  18. dc.connect_time,
  19. dc.net_transport,
  20. dc.net_packet_size,
  21. dr.start_time,
  22. dr.status,
  23. dr.command,
  24. dr.blocking_session_id,
  25. dr.wait_type,
  26. dr.wait_time,
  27. dr.last_wait_type,
  28. dr.wait_resource,
  29. dr.open_transaction_count,
  30. dr.percent_complete,
  31. dr.granted_query_memory
  32. FROM Sys.dm_exec_requests dr WITH(nolock)
  33. RIGHT OUTER JOIN Sys.dm_exec_sessions ds WITH(nolock)
  34. ON dr.session_id = ds.session_id
  35. RIGHT OUTER JOIN Sys.dm_exec_connections dc WITH(nolock)
  36. ON ds.session_id = dc.session_id
  37. WHERE ds.session_id > 50
  38. ORDER BY ds.program_name

用户连接数

  1. SELECT login_name,
  2. Count(0) user_count
  3. FROM Sys.dm_exec_requests dr WITH(nolock)
  4. RIGHT OUTER JOIN Sys.dm_exec_sessions ds WITH(nolock)
  5. ON dr.session_id = ds.session_id
  6. RIGHT OUTER JOIN Sys.dm_exec_connections dc WITH(nolock)
  7. ON ds.session_id = dc.session_id
  8. WHERE ds.session_id > 50
  9. GROUP BY login_name
  10. ORDER BY user_count DESC