关闭

认识数据库连接

437人阅读 评论(0) 收藏 举报

http://www.cnblogs.com/forcertain/archive/2011/01/20/1939808.html

 

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

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要求的连接时,它只是返回到连接池,等待下一个命令来激活它。

     通过 

1 sp_who 'testusers'    // testusers是你建立连接时指定的用户名

     可以查看你当前连接数

connection

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

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

 

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

 

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

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

     首先是正常的程序:

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查看到的,还是那一个。知道这为什么叫正常的程序了吧,符合正常推理,哈哈。

以下是有问题的程序:

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作用(数据库群集)

     

      实验结束,再一次用事实证明连接一定要显式关闭,同样提供了一个简单方法查看我们的程序是不是存在未关闭的连接。

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:118551次
    • 积分:1465
    • 等级:
    • 排名:千里之外
    • 原创:0篇
    • 转载:163篇
    • 译文:0篇
    • 评论:14条
    文章存档
    最新评论