【数据库】食堂大师父与那个连接池的故事

来源:互联网 发布:对数据进行标准化处理 编辑:程序博客网 时间:2024/04/29 19:42

【前言】

      有没有发现你的程序在不涉及数据库时健步如飞,但一旦需要从数据库中存取数据立即变的步履蹒跚?有没有发现,点一个小小的登录键,页面甚至会暂停两到三秒钟才会出现?有没有发现第一次链接数据库一般要“卡”一下,但是接下来再用可能就好很多?想知道为什吗?连接池是一切的答案。



【正文】

     一、为什么


     

      为什么要用链接池呢?众所周知,创建和打开数据存储区连接是一项既耗时又占用大量资源的任务。而在连接池出现以前,一波一波的正常人都是在启动应用程序时立即打开一个数据存储区链接,并在应用程序关闭前保持链接畅通的。听起来好像很简答的样子,嗯,好像不错。但是,另一个问题出现了, 这种方法要求应用程序关闭前链接不能关闭,而维护这些链接同样是需要时间的,但我们更希望数据存储区将大部分的时间用在数据传输上


    

      举一个不太恰当的栗子:食堂只有一个大师父(数据存储区),他既要负责发餐盘(创建链接)也要负责打饭(传输数据) 还要负责刷盘子(维护链接),开始的时候,大家都是买一样菜发一个盘子, 但是(既耗时又占用大量资源)。

     然后我们就采用了一种新方法,餐盘只发一次, 大家一人一个, 食堂(应用程序)不倒闭,餐盘不收回,但是大师父负责定期的餐盘清洗 这样就节省了大师父发餐盘的时间和食堂的餐盘资源。我们都感觉挺好。

     但是随着时间发展,食堂变的更大了, 客户更多了,餐盘更多了(链接), 大师父清洗一次就一天的时间,然后大家就饿了一天,大家都不乐意了,

     因为我们更希望大师父的时间更多的用在做饭,打饭上(数据传输),而尽可能少的时间来刷盘子(维护链接)。

     这时候一个不太正常的人(感激前辈的贡献,可惜没有查到具体的发明人),搞出了一个新的机制,来让大师父少刷盘子,这种机制就是链接池技术。


二 是什么

1.原理:

      即在向数据库发送请求时,连接池只是重新使用处于打开状态的现有链接,而不是创建新的链接。它使用一个链接管理器来维护一个包含可用链接的列表(连接池)。在链接管理器收到一个创建新链接的请求时,检查是否包含可用链接。如果有一个可用链接,则返回该链接;如果没要,且未达到最大链接,则创建一个,达到最大链接则请求进入队列。 

     

     转回到食堂的例子里来,就是说,专门找个饭盘管理员(连接管理器)在食堂待着随时调配餐盘(现实生活中这样,每顿饭都会回收),客户不吃饭的时候就把餐盘放到管理员那儿, 谁要吃饭,先找餐盘管理员, 先看有没有回收回来的(打开但是空闲的链接),没有的话,再看食堂还有没有饭盘(是否达到最大链接数),如果食堂也没有了,就让它先排队等着(请求进入队列)。所以我们其实总在使用链接池技术。


    2.什么时候产生

         字有点多, 那么链接池在代码中长什么样呢?

(本篇所有代码均已VB.net为例)

<span style="font-size:24px;">Connection.open()</span>

     尴尬,,没错就是这句你熟悉的不能再熟悉的代码。


     Connection pool group 是一个为特定ADO.NET提供者管理连接池的对象,在实例化第一个链接时,创建一个链接池组对象。但是只在打开第一个链接时创建第一个链接池。


3.链接在池中生存时间

      默认是4-8分钟, 如果希望在程序即使在长时间的空闲下也保持一个链接,则需要将链接字符串connectionString 中 MinPoolSize 改为1或者一个稍大的值。

       AKA链接生命期: 这个中有一个Load Balancing Timeout 设置,可以控制链接打开的时间,如果超过设定值,则销毁该链接,主要用于增加服务器时,销毁一些链接,减轻原有服务器压力,在新服务器中创建新链接。

三 怎么用

1.goodbye Close” ,Hello “using ”

因为过往我们的程序经常由于


<span style="font-size:24px;">dim cn as sqlconnection = New SqlConnection(cnSettings.ConnectionString)    Cn.open()</span>


之后忘记cn.close 或者某些原因导致close 或者dispose方法无法正常使用导致连接池泄露(链接数不受控制的上涨)

所以前辈们给出了新的方法

<span style="font-size:24px;">Using cn as sqlConnection=New sqlconnction(cnSettings.ConnctionString ) Cn.opern()</span>


Using 块将自动调用Dispose 方法,cmd 对象也是一样。

2.清除链接池

在程序的运行过程中,我们的服务器可能从服务器组中删除或者由于维护而重启停止服务。如果停止服务, 我们的代码极有可能抛出一个包含如下 信息的SqlException

<span style="font-size:24px;">A transport-Level error has occurred when receiving receiving results from the server.(provider:session Provider,error:18-Connection has been closed by peer)</span>


如何处理这种问题呢?

我们引入如下代码:

<span style="font-size:24px;">Private sub btn_click(ByVal sender as system.object,_byval e as system.eventargs) handles btn.click   '一个按钮事件,单击时执行如下代码</span>
<span style="font-size:24px;">Try                                              'try catch 异常处理程序 Displayversion()                                 '执行下边的那个过程Catch xcp as sqlexception                             If xcp.number<>1236 then throw xcp            '如果异常编号不为1236,则继续抛出异常   System.diagnostics.debug.writeline(“Clearing Pools”)  ’输出窗口调试信息   sqlConnection.ClearAllPools()       '清除链接池   Displayversion()                    '再次执行 该过程End try  Public sub displayVersion()          '一段获取数据库版本信息的代码   Dim ver as String =Nothing    Dim cnSettings as sqlConnctionStringBuilder   cnSettings =New SqlConnectionStringBuilder(    “Data Source=.;”+”Database=***;”+”INtergrated Security =True;”+”Max pool Size =5”)   Using cn as sqlConnection =new sqlconnection(cnSettings.ConnectionString )  '创建一个链接字符串    cn.Open()    Using cmd as SqlCommand=cn.CreateCommand()         cmd.CommandText =”Select @@VEersion”         Ver =CType(cmd.ExecuteScalar()),String)    End Using   End Using    MessageBox.Show(ver)End sub</span>


 
【总结】

     小身材,大智慧。 小小一个connection.open () , 我不说你能知道里边有这么多的奥秘? 来吧,让我们一起探索这美妙的程序世界。 加油!

0 0
原创粉丝点击