您的位置:首页 > 数据库

认识数据库连接

2011-01-20 14:14 218 查看
/article/5280891.html

数据库连接,这还用说,都会接触到啊,说的这是这个经常见的数据库连接。

view source

print?

1
Data Source=.;Initial Catalog=test;Persist Security Info=True;User ID=testuser;Password=123456;Min Pool Size=10;Max Pool Size=150;Connection Lifetime=10
这谁不明白啊,这里要说的就是

Min Pool Size=10;Max Pool Size=150;Connection Lifetime=10

这里就说到 数据库连接池 了,默认是启用的,以上的属性就是配置这个连接池的。这也就意味着,当你的页面发送数据库请求的时候,不一定就非要创建数据库连接,而可能是从已存在连接池里,激活一个的连接来处理你的请求的;同样,当你代码中调用Close显式关闭数据库连接的时候,也不一定就是真的关闭数据库连接了,如果当前连接池中没有满足Min Pool Size要求的连接时,它只是返回到连接池,等待下一个命令来激活它。
通过

view source

print?

1
sp_who
'testusers'
// testusers是你建立连接时指定的用户名
可以查看你当前连接数





连接池是怎么按照你的配置如何工作呢??

当第一次连接请求到来时,它会在很短的时间内创建Min Pool Size指定的连接,尽管你的并发请求数可能远没达到这个数目。当并发请求数低于这个值,这以后将不会有连接的的创建和关闭,除非你关闭应用程序;并发请求数目大于这个最小值时,就会创建连接,并发请求数大于Max Pool Size最大值时,这个请求将进入等待队列,等待空闲连接,如果达到应用程序或者数据库限制的时 间还没被处理,就将返回连接超时的异常。

这原理谁不懂啊,是的,程序正常的时候是这样,当程序不正常的时候是什么样呢。。正常的程序:凡是操作数据库的,操作完毕之后都有显式的调用Close()或者Dispose()关闭连接。下面做个试验,同样下面提供的方法,可以验证你的应用程序是否存在没有关闭的连接。本人也是基于这个需求,才做这些试验的。

现如今的程序,涉及数据操作的都是封装好啊,是的,像dataset,datatable等reader以外的操作,都是在数据库操作类处都关闭了。嗯,是的,但是reader,就只有在开发人员用完之后显示关闭了,这就可能由开发人员的素质决定了。不要告诉我,你根本就不用reader,呵呵,那这篇文章跟你没关系了。

就以reader来开始实验,我们把Min Pool Size设为1.

首先是正常的程序:

view source

print?

01
using
(SqlDataReader reader = Maticsoft.DBUtility.DbHelperSQL.ExecuteReader(
"select top 1 * from protuct order by id desc"
))
02
{
03
    
while
(reader.Read())
04
    
{
05
        
Response.Write(reader[
"Name"
].ToString());
06
    
}
07
}
08
using
(SqlDataReader reader2 = Maticsoft.DBUtility.DbHelperSQL.ExecuteReader(
"select top 1 * from users order by userid desc"
))
09
{
10
    
while
(reader2.Read())
11
    
{
12
        
Response.Write(reader2[
"userName"
].ToString());
13
    
}
14
}
这段程序放在一个页面里,无论你怎么刷或者多少人同时请求这个页面,待请求处理结束后,通过sp_who查看到的,还是那一个。知道这为什么叫正常的程序了吧,符合正常推理,哈哈。

以下是有问题的程序:

view source

print?

01
SqlDataReader reader3 = Maticsoft.DBUtility.DbHelperSQL.ExecuteReader(
"select top 1 * from users order by userid asc"
);
02
while
(reader3.Read())
03
{
04
    
Response.Write(reader3[
"userName"
].ToString());
05
}
06
SqlDataReader reader4 = Maticsoft.DBUtility.DbHelperSQL.ExecuteReader(
"select top 1 * from protuct2 order by id asc"
);
07
while
(reader4.Read())
08
{
09
    
Response.Write(reader4[
"Name"
].ToString());
10
}
11
SqlDataReader reader5 = Maticsoft.DBUtility.DbHelperSQL.ExecuteReader(
"select top 1 * from protuct order by id desc"
);
12
while
(reader5.Read())
13
{
14
    
Response.Write(reader5[
"Name"
].ToString());
15
}
16
SqlDataReader reader6 = Maticsoft.DBUtility.DbHelperSQL.ExecuteReader(
"select top 1 * from users order by userid desc"
);
17
while
(reader6.Read())
18
{
19
    
Response.Write(reader6[
"userName"
].ToString());
20
}
可以看到,reader没有显式关闭,为了看效果,多放了几个。

首先,我先一个人正常的刷一下,页面加载完毕后,通过sp_who查看,连接有4个,状态是sleeping,wait command,大于Min Pool Size了,不正常。我如果再刷一下,你猜会是几个,8个??大于4个??再一次次正常的刷,结果还是4个????说明连接执行完毕后会自动返回连接池,没有关闭的请求,就存活了下来,但是有执行操作的请求时,它们依然可以被激活来执行操作。哇哈哈,那岂不是很爽,没有显式关闭连接不会造成任何不良的影响啊。哈哈,但是,没有显式关闭并不代表不关闭啊,根据.net垃圾收集的工作原理,我们知道任何对象在离开它的工作范围之后就成了垃圾,等待被回收,回收的过程中,回收管理器发现对象实现了IDipose(),就会再次激活这个对象,调用它的Dispose(),然后再次成为垃圾,最终被回收。Dispose()调用的时候,是不确定的,因此,连接池中多余的连接也会在未来的某个时间关闭,那么就有可能造成程序的不稳定,因为这个连接可能此时已经被激活处理其它请求,又可能被后来的请求已显式关闭等等,也或许微软已通过某种机制让上述担心成为了多余。但是不正常代码,影响远不止这些。。。。。

请注意前面是一次次正常的刷新,也就是我自己等页面出来以后,再刷新页面,下面我强制按住F5,让页面连续刷新,再次通过sp_who查看,结果大吃一惊,此时sleeping的连接,达到了几十个,如果很多人呢同时访问呢,那连接池很快就会被这占满,不稳定的影响,很快就会被放大很多倍。因些如何判断你的应用程序存在未关闭的连接,在访问高峰期或者自己模拟大量的并发请求,查看如果状态是sleeping的连接大于你设定的Min Pool Size值,肯定就是存在了。

下面再说说Connection Lifetime

官方解释:每当一个连接使用完后释放回连接池,如果当前时间减去该连接建立的时间的值大于这个参数设定的值(秒),该连接被销毁。0表示lifetime没有上限。

根据表面意思,没显式关闭的连接也会在这个值指定的时间来临时关闭,那太好了,管它reader关没关呢,设个较小lifttime不得了。但是令人疑惑的是,我把此值设为1,不正常代码的产生的多余连接并没有在1秒后销毁,而是等待一个不太确定的时间,这个可能就是垃圾收集来临的时间,同样正常代码情况下,将此值设为60,显式调用的如果超出Min Pool Size的连接会被立即关闭,在Min Pool Size范围内的连接一直存活。这么看来此值没一点作用啊。

搜索了搜索发现有篇文章提到了作用:

Connection Lifetime作用(数据库群集)

实验结束,再一次用事实证明连接一定要显式关闭,同样提供了一个简单方法查看我们的程序是不是存在未关闭的连接。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: