数据库连接及线程池技术原理解析._第1页
数据库连接及线程池技术原理解析._第2页
数据库连接及线程池技术原理解析._第3页
数据库连接及线程池技术原理解析._第4页
数据库连接及线程池技术原理解析._第5页
已阅读5页,还剩8页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、数据库连接及线程池曾几何时,记住了一句话:建立数据库连接是一个代价高昂的过程 ”,也从那时开始,我在构建系统时,一旦建立起了数据库连接,就保存起来,任何要用数 据库的地方,都使用这个数据库连接对象进行操作。这样的行为,在以前写的单线程程序中,倒也可以接受,但在这次写的多线 程程序中,就出现问题了。在这次的程序中,最开始设计时,在工作线程类中, 设置了一个SqlConnection 的静态成员以接受系统中已经建立起的数据库连接对 象。大致的代码如下:P ublic class NoPo olThreadSystem.Data.SqlClie nt.SqlC onn ectio nP ublics

2、taticDatabaseC onn ecti on = nu II;p rivate System.Threadi ng.Thread WorkThread = nu II;p rivate bool Con ti nue = false;p ublic void Start(if (WorkThread = nullThreadStart workf un = new ThreadStart(DoWork;WorkThread = new Thread(workf un;Con ti nue = true;WorkThread.Start(;p rivate void DoWork(nul

3、l;System.Diag no stics.Debug.Assert(DatabaseC onn ectio nwhile (Con ti nue/省略了使用数据库连接对象进行操作的代码Thread.Slee p(300;/ end whilep ublic void Stop(if (WorkThread != nullCon ti nue = false;在主程序中,使用下面的代码来启动工作线程SqlC onn ecti on conn ecti on = nu II;NoP oolThread threads = new NoP oolThread99;p rivate void bu

4、tt on 1_Click(object sen der, Eve ntArgs e conn ecti on = new SqlC onn ectio n( GetCo nn ectStri ng(;connection.Open(;NoPo olThread.DatabaseC onnection = connection;for ( int i=0; ithreadsi = new NoPo olThread(;threadsi.Start(;凭借以往的经验,满心期望着:NoP oolThread 你给我好好干吧,成功就在眼前。殊不知,异常马上就出现,基本上是说:已有打开的与此命令相关联

5、的DataReader,必须首先将它关闭。ExecuteNonQuery 要求已打开且可用的连 接。连接的当前状态为已关闭”。然后把threads数组长度改成1,即又恢复到只有一个线程使用数据库 连接对象时,就又恢复正常。这样就说明了,在多个线程中使用同一个SqlConnection对象进行数据库操作的想法是不现实的也是行不通的。于是,就大着胆子,冒着巨大的代价”,进行修改,在任何使用SqlConnection的地方,都临时创建的SqlConnection对象一个对象,但是要创建对象,需要连接字符串啊,怎么来呢,不想重新写一遍,就用现成 的、已经传到线程对象里面的哪个数据库连接对象里面的连接字

6、符串 吧,于是修改代码如下:p rivate void DoWork(System.Diag no stics.Debug.Assert(DatabaseC onn ectio n != n ull;newSqlC onn ecti onconnectionSqlC onn ectio n( DatabaseC onn ectio n.C onn ectio nStri ng;while (Con ti nue使用conn ection对象Thread.Slee p(300;/ end whileconn ectio n.Close(;3.2 SqlConnection 的连接这样修改的结果,

7、每个线程使用自己的SqlConnection对象对数据库进行操作,使各个线程之间互不影响。根据测试,程序可以顺畅运行,而 且在性能上没有明显损失,这多少有些以为,于是继续查找资料。由于 使用的时SqlConnection对象,所以就以它为线索,首先从MSDN开始,MSDN给出的解释有如下内容:SqlCo nn ection对象表示与SQL Server数据源的一个唯一的会话。 对于客户端/服务器数据库系统,它等效于到服务器的网络连接。SqlConnection 与 SqlDataAdapter禾0 SqlCommand 一起使用,可以在连 接Microsoft SQL Server数据库时提高

8、性能。对于所有第三方 SQL服务 器产品以及其他支持 OLE DB的数据源,请使用 OleDbCo nn ectio n。当创建SqlConnection的实例时,所有属性都设置为它们的初始 值。有关这些值的列表,请参见SqlCo nn ection构造函数。如果SqlCo nn ection超出范围,则不会将其关闭。因此,必须通过 调用Close或Dis pose显式关闭该连接。它们在功能上是等效的。如果 将连接池值Pooling设置为true或yes,则也会释放物理连接。还可以 打开using块内部的连接,以确保当代码退出 usi ng块时关闭该连接。注意:若要部署高性能应用程序,则必须使

9、用连接池。在使用用 于SQL Server的.NET Framework数据提供程序时,不必启用连接池, 因为提供程序会自动对此进行管理,不过您可以修改某些设置。从上面的解释来看,我修改后的代码,无意间启用了数据库连接池 因为除非你在连接字符串里面明确禁用连接池功能,否则默认的数据 库连接是从连接池中获得连接的。3.3连接池的相关概念这里,既然提及了连接池,自己在这方面的认识又很模糊,于是就自 己给自己了一个学习连接池的机会。连接池及ADO.NET连接到数据库服务器通常由几个需要很长时间的步骤组成。必须建立物理通道 (例如套接字或命名管道),必须与服务器进行初次握手,必须分析连接字符串信 息,

10、必须由服务器对连接进行身份验证,必须运行检查以便在当前事务中登记,等等。这就是建立数据库连接的代价,但仍然只是定性的描述。实际上,大多数应用程序仅使用一个或几个不同的连接配置。这意味 着在执行应用程序期间,许多相同的连接将反复地打开和关闭。为了使 打开的连接成本最低,ADO.NET使用称为连接池的优化方法。连接池是一种在打开数据存储区的连接时提高应用程序性能的机制, 可以显著提高应用程序的性能和可缩放性。使用连接池减少新连接需要 打开的次数。池进程保持物理连接的所有权。通过为每个给定的连接配置保留一组活动连接来 管理连接。只要用户在连接上调用Open,池进程就会检查池中是否有可用的连接。如果某

11、个池连接可用,会将该连接返回给调用者,而不是打开新连接。应用程 序在该连接上调用Close时,池进程会将连接返回到活动连接池集中,而不是真正 关闭连接。连接返回到池中之后,即可在下一个Open调用中重复使用。只有配置相同的连接可以建立池连接 。ADO.NET同时保留多个池,每个配置一个 池。连接由连接字符串以及 Windows标识(在使用集成的安全性时)分为多个 池。池连接可以大大提高应用程序的性能和可缩放性,考虑一个访问SQL Server数据库的典型ASP .NET或 WebServices应用程序。客户端应用程序每次需要查询数据 库时,就会在服务器端代码中进行往返,以打开SqlConne

12、ction来执行查询。在许多此类应用程序中,这一代码以相同凭据一次又一次地连接到相同数据库。理论 上,这意味着客户端应用程序每次需要执行查询时,服务器端代码需要执行三个操 作一一登录到数据库(需要检查所提供的凭据、执行查询、然后注销。连接池可以 真正地提高此类应用程序的性能 一一通过将内部连接存储在池中,并在以后进行重 复利用,就不再因为登录数据库以及从中注销而降低性能。对SqlConnection对象的Open和Close方法的调用可以短时间内返回,从而可以提高代码的性能和响应 速度(请参见3.1图。£.11:' '! ItSy匸图3.1典型ASP.NET或WebS

13、ervices应用程序中的连接池默认情况下,ADO.NET中启用连接池。除非显式禁用,否则,连接在应用程序中 打开和关闭时,池进程将对连接进行优化。还可以提供几个连接字符串修饰符来控 制连接池的行为。有关更多信息,请参见 MSDN中的使用连接字符串关键字控制 连接池”在调用SqlConnection对象的Close方法时,SQL Client .NET数据提供程序并不实 际关闭内部连接。相反,数据提供程序将该内部连接存储到一个池中,以便在以后 再次使用。甚至在 SqlConnection对象被处理之后,该内部连接也保留在池中。如果在以后使用相同连接字符串和凭据调用SqlConnection对象

14、的Open方法,将会再次使用同一内部连接与数据库进行通信。Conn ection 对象的 Close 或 Dis pose 方法,因此,微软建议在使用完连接时一定要关闭或断开连接,以便连接可以 返回池。要关闭连接,可以使用也可以通过在 C#的using语句中或在 Visual Basic的 Using语句中打开所有 连接。不是显式关闭的连接可能不会添加或返回到池中。例如,如果连 接已超出范围但没有显式关闭,则仅当达到最大池大小而该连接仍然有 效时,该连接才会返回到连接池中。不是显式关闭的连接可能无法返回 池。例如,如果连接已超出范围但没有显式关闭,则仅当达到最大池大 小而该连接仍然有效时,该连

15、接才会返回到连接池中。参见下面的示 例。另外,如果你希望确认是否真正再次利用了同一内部连接,可以使用.NET Reflection中的功能以可编程方式访问私有 InnerConnection属性的内 容。以下代码(其需要对System.Reflection命名空间的引用在Using代码块中 打开一个 SqlConnection,并存储 SqlConnection 的 InnerConnection属性的值。通过利用Using代码块,在该代码块的末尾隐式处理了SqlConnection。此代码在Using代码块中打开另一个SqlConnection,并存储SqlConnection的InnerC

16、onnection属性的值。最后,此代码对比InnerConnection属性的内容,确认它们实际上为同一对象。stri ng strCo nn = "Data Source=.SQLEx press;l ntegrated Secunty=True;"Prop ertyI nfo propInnerConn;propInnerConn = typ eof(SqlC onn ectio n.Get Prop erty("I nn erC onn ectio n".Bindin gFlags.N onP ublic | Bindin gFlags .In

17、sta nee;object objInnerConnI, objlnnerConn2;using (SqlC onn ectio n cn = new SqlC onn ectio n(strC onncn.Open(;objInnerConnI = propinn erC onn .GetValue(c n, n ull;cn .Close(;using (SqlC onn ectio n cn = new SqlC onn ectio n(strC onncn.Open(;objlnnerConn2 = propinn erC onn .GetValue(c n, n ull;cn .C

18、lose(;Con sole.WriteL in e(obj InnerConnI = objlnnerConn2;两个SqlConnection对象是在不同的 Using代码块中创建的,所以其资 源将在每个Using代码块的末尾被清除。innerConnection属性的内容及其 所封装的物理连接没有被处理,而是存储在池中,以便在以后被再次利用。注意 如果在连接字符串中禁用了连接池 (稍后将解释如何禁用,将 会看到此内部连接不能被重复利用。连接池的创建和清除在初次打数据库开连接时例如调用SqlCo nn ectio n.Open方法时,池按进程、按应用程序按Win dows标识来建立进程将根

19、据完全匹配算法创建连接池,该算法将池与连接中的连接字符串 关联。每个连接池与不同的连接字符串关联。打开新连接时,如果连接 字符串并非与现有池完全匹配,将创建一个新池。 域、按连接字符串以及(在使用集成的安全性时) 池连接。ADO.NET 2.0 引入了两种新的方法来清除池: ClearAllPools禾0 ClearPool。 ClearAllPools清除给定提供程序的连接池, ClearPool清除与特定连接关联的连接池。如果在调用时连接正在使用,将 进行相应的标记。连接关闭时,将被丢弃,而不是返回池中。连接的添加和移除连接池是为每个唯一的连接字符串创建的。当创建一个池后,将创建多个连接

20、对象并将其添加到该池中,以满足最小池大小的要求。连接根据需要添加到池中, 但是不能超过指定的最大池大小(默认值为 100)。连接在关闭或断开时释放回池 中。在请求SqlCo nn ection对象时,如果存在可用的连接,将从池中获取该对象。连接 要可用,必须未使用,具有匹配的事务上下文或未与任何事务上下文关联,并且具 有与服务器的有效链接。15秒)。如果池进程在连接超连接池进程通过在连接释放回池中时重新分配连接,来满足这些连接请求。如 果已达到最大池大小且不存在可用的连接,则该请求将会排队。然后,池进程尝试 重新建立任何连接,直到到达超时时间(默认值为 时之前无法满足请求,将引发异常。Clos

21、e或Dis pose关闭的未用连连接池进程定期扫描连接池,查找没有通过接,并重新建立找到的连接。如果应用程序没有显式关闭或断开其连接,连接池进 程可能需要很长时间才能重新建立连接,所以,最好确保在连接中显式调 用 Close 和 Dispose如果连接长时间空闲,或池进程检测到与服务器的连接已断开,连接池进程会 将该连接从池中移除。注意,只有在尝试与服务器进行通信之后才能检测到断开的 连接。如果发现某连接不再连接到服务器,则会将其标记为无效。无效连接只有在 关闭或重新建立后,才会从连接池中移除。如果存在与已消失的服务器的连接,那么即使连接池管理程序未检测到已断开 的连接并将其标记为无效,仍有可

22、能将此连接从池中取出。这种情况是因为检查连 接是否仍有效的系统开销将造成与服务器的另一次往返,从而抵消了池进程的优 势。发生此情况时,初次尝试使用该连接将检测连接是否曾断开,并引发异常。上述连接的添加和移除,全都是由后台运行的池进程管理的。禁用连接池您可能不希望使用连接池。例如,如果正在使用一个直接与数据库进行通信的 简单 Windows应用程序,那么可能希望禁用连接池。在采用这一架构时,各个客 户端应用程序需要自己的连接。在启用连接池时,每个应用程序的连接被放入池 中,如果在清除连接池之前重新打开该连接,将重复利用放入池中的连接。所以, 如果应用程序频繁重复使用连接,那么在启用连接池的情况下

23、,对 SqlConnection.Open的调用将会更快速地返回。但是,这种方法将会导致在任意给 定时刻存在许多活动的数据库连接。禁用连接池将会降低任意时刻的活动数据库连 接数目,但这样会强制所有对 SqlCo nn ectio n.Open的调用都建立一个新的数据库连 接。如果希望禁用连接池,可以通过向连接字符串中添加Pooling=False,逐个连接地禁用连接池。幸运的是,在ADO.NET 2.0中不再需要记忆诸如此类的属性。如果存在疑问,可以检查 SqlCo nn ectio nStri ngBuilder类的选项。在这个类中可以找到 一个Pooling属性,其取值为Boolean类型

24、。默认情况下,此值被设置为 True。将 该值设置为False将会禁止将该连接放入池中。因此,在调用SqlConnection对象的Close方法时,将会关闭与数据库的实际连接。注意 在偶尔进行连接”的Windows应用程序中,使用连接池可能很有帮助, 具体取决于应用程序。如果应用程序希望定期重新连接到数据库,则可以发挥连接 池的作用,将与数据库的物理连接保持打开状态,至少暂时如此。如果在从池中删 除该物理连接之前,应用程序尝试重新连接到该数据库,则连接池逻辑(po oli nglogic将会重新使用与该数据库的物理连接。查看数据库连接在使用了数据库连接池的情况下,那么建立到数据库上的连接到底怎么样呢, 这可以使用 Windows的性能查看器来看

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论