数据库连接池〔翻译〕
原文:http://www.codeproject.com/KB/dotnet/ADONET_ConnectionPooling.aspx
你是否能够感觉到当您在客户端使用相同的查询向服务器提交查询信息的时候结果的返回会越来越快。从服务器端将数据返回数据到客户端有一种机制产生了以上的结果,而这种机制就是在ADO之间建立连接
我们通常是把与数据库连接的信息存储在配置文件中,利用它在系统中频繁地打开与关闭与数据库的连接。这样我们不管是访问多大或多小的数据我们都是用的一样的连接。
IIS中的ADO.NET有一种叫做连接池的技术是解决以上问题很好的方法。当应用程序第一次发生请求的时候建立与数据库的请求而当系统关闭数据库连接的时候。ADO.NET没有完全的销毁连接,而是把这个连接对象放到连接池中并保留对他的引用。当下一次发生请求的时候ADO.NET从连接池中调出连接运用到本次查询中。这样可以提高一定的效率。
当我们利用ADO.NET向数据库发送查询的时候,在相同的进程和应用程序域中ADO.NET利用确定的连接字符串匹配连接池中的连接对象。如果找到并且该连接空闲可用那么就得到该连接用于本次请求,否则就建立新的连接并把该连接添加到连接池中。在向连接池添加连接的时候不能超过连接池最大连接数量。
我们可以利用Close() or Dispose()方法在利用后立即销毁连接二而不是等到GC来释放连接消耗的资源。
在ADO2.0中新增了两个清理连接池的方法ClearAllPools,ClearPool
除了注意以上列表以外还有一个需要注意的。我们在连接字符串中尽量利用USERID,PQSSWORD来建立连接,这样一个客户可以利用其他客户建立的连接。否则则会为每个客户建立连接。
在ORACLE中,打开类似PL/SQL的客户端工具执行SELECT * FROM V$SESSION WHERE PROGRAM IS NOT NULL
问题描述:我们获取连接超过连接池最大值时产生如上异常。通常连接池最大值为100。当我们获取连接超过最大值时,ADO.NET等待连接池返回连接而超时,这样将抛出如上异常
解决办法:首先要做的是在我们使用连接后立即关闭连接。如果没有关闭连接那么连接将保存到连接池中知道GC来销毁。这种情况下你以为连接池没有到达最大值但实际上连接池已经到达了最大值
其次我们可以通过连接字符串中的Max Pool Size = N;来动态扩大连接池中的连接最大数量。
在者就是关闭连接池
A transport-level error has occurred when sending the request to the server. (provider: Shared Memory Provider, error: 0 - Shared Memory Provider: )
问题描述:ADO.NET以为数据库存在某一确定连接但是数据库由于重启而丢失了所有连接。
解决办法:对于ORACLE如果你用ODP,NET访问数据库那么你应该在连接字符串里加上Validate Connection=true或validcon=true
对于对于MS SQLSERVER,你可以用SqlConnection.ClearPool静态方法清除连接池。该方法在SqlClient,OracleClient 中都有。
对于.net1.1下的MS SQLSERVER
a:重建连接池销毁无用连接池
b:捕获异常循环刷新连接直到ADO.NET和数据库保持同步。
对于此确实没有什么好的解决方案。
1:合并数据库连接
与数据库服务器建立连接是非常消耗系统资源的,如果某个系统需要查询某个数据库服务那么必须首先建立起与该数据库的连接然后再执行查询。你是否能够感觉到当您在客户端使用相同的查询向服务器提交查询信息的时候结果的返回会越来越快。从服务器端将数据返回数据到客户端有一种机制产生了以上的结果,而这种机制就是在ADO之间建立连接
我们通常是把与数据库连接的信息存储在配置文件中,利用它在系统中频繁地打开与关闭与数据库的连接。这样我们不管是访问多大或多小的数据我们都是用的一样的连接。
IIS中的ADO.NET有一种叫做连接池的技术是解决以上问题很好的方法。当应用程序第一次发生请求的时候建立与数据库的请求而当系统关闭数据库连接的时候。ADO.NET没有完全的销毁连接,而是把这个连接对象放到连接池中并保留对他的引用。当下一次发生请求的时候ADO.NET从连接池中调出连接运用到本次查询中。这样可以提高一定的效率。
2:创建连接池
连接池和连接字符串是紧密联系的。一个连接池有进程,应用程序域以及连接字符串来确定的。(process,domain ,connection string)当我们利用ADO.NET向数据库发送查询的时候,在相同的进程和应用程序域中ADO.NET利用确定的连接字符串匹配连接池中的连接对象。如果找到并且该连接空闲可用那么就得到该连接用于本次请求,否则就建立新的连接并把该连接添加到连接池中。在向连接池添加连接的时候不能超过连接池最大连接数量。
我们可以利用Close() or Dispose()方法在利用后立即销毁连接二而不是等到GC来释放连接消耗的资源。
3:删除和清理连接池
当应用程序被卸载的时候连接池也随之销毁。在我们的ASP.NET系统中连接池在第一次请求的时候建立当重启IIS的时候销毁。连接池依赖于我们的IIS而不是我们的开发环境。因此你不能通过关闭DEV来销毁连接池。在ADO2.0中新增了两个清理连接池的方法ClearAllPools,ClearPool
4:通过连接字符串来控制连接池
下表列出连接字符串中有关连接池设置的选项Name | Default | Description |
Connection Lifetime | 0 |
When a connection is returned to the pool, its creation time is compared with the current time, and the connection is destroyed if that time span (in seconds) exceeds the value specified by Connection Lifetime. A value of zero (0) causes pooled connections to have the maximum connection timeout. |
Connection Timeout | 15 | Maximum Time (in Secs) to wait for a free connection from the tool |
Enlist | 'true' |
When true, the pooler automatically enlists the connection in the creation thread's current transaction context. Recognized values are true, false, yes, and no. Set Enlist = "false" to ensure that connection is not context specific. |
Max Pool Size | 100 | The maximum number of connections allowed in the pool. |
Min Pool Size | 0 | The minimum number of connections allowed in the pool. |
Pooling | 'true' | When true, the SQLConnection object is drawn from the appropriate pool, or if it is required, is created and added to the appropriate pool. Recognized values are true, false, yes, and no. |
Incr Pool Size | 5 | Controls the number of connections that are established when all the connections are used. |
Decr Pool Size | 1 | Controls the number of connections that are closed when an excessive amount of established connections are unused. |
除了注意以上列表以外还有一个需要注意的。我们在连接字符串中尽量利用USERID,PQSSWORD来建立连接,这样一个客户可以利用其他客户建立的连接。否则则会为每个客户建立连接。
5:一个连接字符串的例子
initial catalog=Northwind; Data Source=localhost; Connection Timeout=30; User Id=MYUSER; Password=PASSWORD; Min Pool Size=20; Max Pool Size=200; Incr Pool Size=10; Decr Pool Size=5;6:查看用ADO.NET建立的连接池
在MS SQLSERVER中,打开查询分析器执行EXEC SP_WHO在ORACLE中,打开类似PL/SQL的客户端工具执行SELECT * FROM V$SESSION WHERE PROGRAM IS NOT NULL
7:连接池中常见的异常
Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached问题描述:我们获取连接超过连接池最大值时产生如上异常。通常连接池最大值为100。当我们获取连接超过最大值时,ADO.NET等待连接池返回连接而超时,这样将抛出如上异常
解决办法:首先要做的是在我们使用连接后立即关闭连接。如果没有关闭连接那么连接将保存到连接池中知道GC来销毁。这种情况下你以为连接池没有到达最大值但实际上连接池已经到达了最大值
其次我们可以通过连接字符串中的Max Pool Size = N;来动态扩大连接池中的连接最大数量。
在者就是关闭连接池
A transport-level error has occurred when sending the request to the server. (provider: Shared Memory Provider, error: 0 - Shared Memory Provider: )
问题描述:ADO.NET以为数据库存在某一确定连接但是数据库由于重启而丢失了所有连接。
解决办法:对于ORACLE如果你用ODP,NET访问数据库那么你应该在连接字符串里加上Validate Connection=true或validcon=true
对于对于MS SQLSERVER,你可以用SqlConnection.ClearPool静态方法清除连接池。该方法在SqlClient,OracleClient 中都有。
对于.net1.1下的MS SQLSERVER
a:重建连接池销毁无用连接池
b:捕获异常循环刷新连接直到ADO.NET和数据库保持同步。
对于此确实没有什么好的解决方案。