长时间保持数据库连接是否安全?

43

我有一个连接到远程数据库的.Net客户端应用程序。 在客户端应用程序的整个生命周期(几个小时)中,保持单个数据库连接开启是否安全?

如果我运行多个(10或100)客户端,上述答案是否仍然适用?

9个回答

33
绝对可以这样做,这就是客户端-服务器应用程序的工作原理。如果使用三层应用程序,应用程序服务器将始终保持一组连接开放。可扩展性是一个问题,或者至少在机器的内存比现代设备少的时代曾经是问题。对于两层(客户端-服务器)应用程序,每个客户端都会打开并保持连接。这有几个影响:
  • 每个连接使用一定的内存,因此大量(相对)空闲的连接将占用机器内存。然而,现代64位服务器可以拥有数十或数百GB的内存,因此它可以支持非常大数量的这种连接。
  • 如果事务在客户端机器上未提交,则锁定将保持打开状态,直到事务被关闭。当某人开始执行事务,离开吃午饭并忘记他们已经离开时,这会导致一类问题。这将锁定事务引用的任何记录数小时。
  • 然而,事务可以轻松地涵盖对数据库的多个访问,这在连接池中更难实现。

池化架构在三层架构中很常见,应用服务器和数据库之间只有有限数量的连接。查询只需使用下一个可用的连接,更新会立即提交。这样可以节省资源,因为您只有有限数量的连接处于打开状态,并且(与乐观并发策略结合使用)将消除大量潜在的应用程序并发问题。

为了使用长事务(即覆盖多个对数据库的调用的事务),必须将事务与连接分离。这是TP监视器的基本架构,并且有一些标准协议,例如XAOLE Transactions来支持此功能。如果此类型的外部管理事务不可用,则应用程序必须构建一个补偿事务,以撤消应用程序事务所做的更改。工作流管理系统通常使用此类型的架构。


27

每个业务操作都要开启和关闭连接

如果你正在谈论一个客户端/服务器应用程序,我建议在使用完连接后立即关闭它。虽然每个单独的应用程序实例可能会花费一些性能来打开连接,但整个应用程序将更好地扩展。这在某种程度上取决于您使用的数据库服务器。SQL Server将根据安装在其上的硬件处理不同数量的并发连接。如果要将客户端/服务器应用程序扩展到数千个桌面,则小型DB服务器可能无法处理所有具有打开连接的桌面,但很可能可以处理仅打开某些连接的数千个桌面。

几年前,我亲眼见证了这种情况。最初部署在几个部门的应用程序没有问题,但随后在整个组织中部署。应用程序很快变得非常缓慢。该组织考虑购买一块非常昂贵的硬件为他们的DB服务器获得一些性能。我建议他们在每个业务操作之后打开和关闭db连接。幸运的是,他们已经设计了这样的应用程序,因此这不是一个困难的更改。他们进行了更改,并在每周网络更新期间推出。翌日,应用程序性能显著提高。他们节省了数千美元。


12
长时间连接的难点在于你可能无法完全确定它们是否仍然存在。网络故障、服务器重新启动或有状态防火墙忘记部分状态都可能导致“陈旧”连接,这些连接看起来是打开的,但当你尝试使用它时会出现错误。
连接池方案通常通过设置一些系统来定期检查池中的连接是否正常,或者在闲置连接超时后将其丢弃,从而解决这个问题。
一般来说,在分布式系统中,你需要编写代码以处理各种失败情况,长时间保持连接打开会使这更加困难——但如果你愿意这样做,那就太棒了。

4

虽然具体细节很重要,但通常保持连接长时间不断开是没有问题的。

如果您的应用程序使用连接池技术,则池中的连接插槽通常会保持连接状态,直到需要它们。

除了极为罕见的基于连接授权模型外,维护连接本身消耗的资源可以忽略不计。

在TCP上运行的SQLServer客户端每隔30秒发送keepalives。 (Keepalives实质上是0长度的TCP数据包),通常被认为是可忽略的流量。

如果您在带宽非常小或WLAN链接不可靠的环境中操作,则增加TCP keepalive间隔可能有助于提高长时间连接保持活动状态的机会,并减少电线上的“闲聊”数量。

使用连接池有利有弊。

反对使用池:

消除了环境污染的可能性 - 其他查询设置特殊环境选项可能会干扰查询执行(xact_abort,事务隔离级别等)

如果已配置/许可的连接限制生效,则应用程序中的空闲连接是其他应用程序无法使用的连接。

反对每次连接:

连接设置(特别是安全连接设置)需要客户端和服务器之间进行多次额外的往返 - 往返往往是WAN应用程序的性能杀手。


2

实际上,这取决于您拥有的具有开放连接的客户端数量以及是否使用任何类型的连接池。如果您是三层系统,并且中间层启用了连接池,则客户端设置不适用。如果您没有使用中间层,现在是考虑它的时候了,如果您担心与服务器的连接数,则此中间层将帮助您更好地管理它。

每个打开的连接都会在服务器上消耗一定量的内存并增加一些开销。如果您是一个二层系统,其中客户端直接与服务器通信,则需要查看服务器的规格和客户端数量,以确定保持连接开放是否值得。如果您是二层系统,并且有成千上万个活动客户端,则可能不想保持它们全部打开...如果您是二层系统,并且只有几十个客户端,则保持它们打开。


1

一般来说,你不应该像这样保持连接处于打开状态。.NET拥有一个ADO.NET连接池系统,它可以完美地实现你想要做的事情,并且效果更好。;-)

更新:我是个“脑残”。反应过度了。这里不适用。

-Oisin


我认为他在谈论每个客户端直接连接到数据库的情况。在这种情况下,连接池是无法帮助的... - Dave Markle
连接池是客户端的,那么为什么它不能在这种情况下帮助呢? - hangy
1
打开一个连接并保持它,不需要池化。 - liggett78
1
连接池只在所有连接都是在同两个系统之间时才起作用,比如中间层的应用服务器和数据库管理器之间。如果客户端有自己的连接,就无法对其进行连接池化处理。 - ConcernedOfTunbridgeWells

1

当你长时间保持事务打开时(在某些隔离级别下),你才会真正遇到问题。

虽然有许可连接限制,并且连接确实会占用服务器内存,但连接越少越好。


1

这是安全的。这就是池化所做的事情...在程序运行期间保持连接打开,并将其用于不同的查询。

但是您可能需要注意数据库连接超时。连接会变得陈旧,您将开始收到奇怪的错误。要么在数据库中设置超时值为非常大的值,要么使用偶尔的虚拟查询来保持连接。


0

这取决于数据库以及您对其的使用方式。通常打开和关闭任何连接都需要付出一定的代价。例如,如果您在移动设备上使用 SQLCE(SQL Server Compact Edition),那么建议您将连接保持打开状态,因为打开和关闭连接的代价不值得麻烦。

相反地,如果您正在使用多用户数据库,则需要更加谨慎地管理这些连接。正如已经提到的,ADO.Net 连接池可以很好地帮助您管理效率。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接