0

考虑建立与 RDBMS 的连接,然后拔出网络插头。(如果连接通过 NAT 网关,您将获得相同的效果,并且网关决定清除该连接。)

此时,RDBMS 服务器正在等待永远不会发生的查询或其他任何事情。并且客户端不会关闭 TCP 连接,因为它不再在该网络上。据推测,服务器也不会关闭它,因为它仍然认为连接是打开的。

典型的 RDBMS 是否通过超时和/或通过 TCP 实现简单的保活机制来处理这个问题?有人对 Oracle、SQL Server 和 MySQL 有这方面的经验吗?

编辑; 更多挖掘表明 mysql 在 8 小时不活动后清除连接。

4

6 回答 6

1

这是一个相当广泛的问题。让我给你一个广泛的答案。

在客户端/服务器时代,这将是一个更大的问题,因为客户端保持与数据库的持久连接。如今,出于可扩展性和其他原因,应用程序通常以“断开连接”的方式编写,它们与数据库建立连接以获取其数据,然后立即断开连接。换句话说,应用程序根据需要请求连接。

当发生“原子”操作(即整个操作必须从头到尾成功完成)时,该操作被包装在事务中。如果在事务期间的任何时候数据库连接被切断,数据库系统将“回滚”操作,将任何受影响的记录置于事务开始之前的相同状态。

超时确保到数据库的任何杂散连接不会永远保持打开状态。

于 2009-06-06T23:29:37.687 回答
1

当客户端或服务器断开底层 TCP 连接时,另一端的 TCP/IP 堆栈会检测到这一点并通知应用程序。您可以确保数据库服务器关闭连接(并回滚任何未提交的事务)。

更新:网络故障看起来就像对方消失了一样。双方都会设置套接字超时、重试等,以便他们可以优雅地处理这些故障。Jonathan 在评论中提出了一个有趣的子问题,如果客户端显式断开连接而不以任何方式终止事务,则服务器会执行隐式事务提交。

于 2009-06-06T23:30:13.817 回答
0

Oracle JDBC 驱动程序在连接类上提供了一个专有的 ping() 方法,如果连接被认为是“活动的”,则该方法返回 true。

不幸的是,ping() 是由一个白痴实现的。它向服务器发送一个“select 'x' from dual”查询到服务器,这远非一个低影响的查询,因为存在文字“x”,这给查询缓存带来了困难。

每次从池中借用连接时,我们都会从我们的应用服务器调用 ping(),直到它几乎杀死了我们的 oracle 服务器。

不建议。

于 2009-06-07T14:46:31.913 回答
0

你所说的具体情况并没有真正发生。仅仅因为建立了连接,并不意味着 RDBMS 正在“等待”查询到达。它可能只是简单地注意到连接的存在,启动一个异步读取操作,然后继续它的业务。

如果异步读取永远不会完成是一个问题,那么当然,RDBMS 可以实现一个周期性的“ping”机制来确定连接是否仍然打开。正如我想你已经知道的那样,TCP/IP 连接只有在两端都打开时才打开,所以如果 RDBMS 向不再存在的客户端发送“ping”,那么写入操作会使连接超时,并且服务器端将关闭。人们会期望 RDBMS 注意到这一点,并销毁与连接相关的任何服务器端资源。

于 2009-06-06T23:42:06.897 回答
0

在 SQL Server 中,连接(您可以通过 sp_who 看到这一点)被关闭并且未提交的事务被回滚。

我在客户端看到的是,来自客户端的同一连接的后续尝试(在重新连接 VPN 或 NAT 的情况下)通常会导致客户端出现传输错误,并在客户端创建新连接同一窗口中后续批次的 SSMS 情况。

于 2009-06-07T16:52:20.190 回答
0

数据库连接通常是池化的,因此您不必每次都因建立连接而受到惩罚。应用程序服务器提供此功能,并且它们通常提供灵活性来刷新连接池并在检测到此陈旧连接状态时重新建立其池中的所有连接。

于 2009-06-07T01:40:56.563 回答