当 Firebird 2.5.6 上的池化 = true 时,c# 应用程序中的连接不会超时



当我在 c# 应用程序上使用带有Pooling=true的连接字符串连接到 Firebird 2.5.6 超级服务器时,我断开了与网络的连接,然后

FbConnection fbc = new FbConnection(connstring);

fbc.Open()- 永远不会超时,可以等待很长时间,并且在这里陷入僵局。

但是当我将连接字符串与Pooling = false一起使用时,没关系,几秒钟后代码转到下一行。

此外,当我使用Pooling = True和之前.Open()我这样做:

FbConnection.ClearAllPools();

比它也可以 - 几秒钟后代码转到下一行。

为什么使用pooling = true,如果之前没有清除所有池,我就会遇到这种死锁?

您的问题似乎不是死锁,而是阻塞问题(可能在网络I/O上)。

当您使用Pooling=true时,Firebird ADO.net 提供程序会保持与服务器的物理连接打开以供重用。只有代码中使用的句柄才会关闭。当您打开"新"连接时,它将首先尝试从池中获取物理连接并将其交给您(可能会进行一些验证),如果池中没有连接,它将创建一个新的物理连接。

如果断开与网络的连接,现有连接可能仍处于打开状态,但不再有效。尝试写入连接可能会成功(由于缓冲区)或阻塞,尝试读取也可能阻塞。此阻塞持续多长时间取决于许多因素(断开连接的方式、网络配置、套接字超时等)。这可能意味着,当尝试使用断开连接时已打开的套接字时,读取或写入可能会无限期阻塞。如果网络连接已恢复,现有连接可能会再次开始工作,或者可能确实断开,但同样,根据断开连接的性质,可能需要一些时间才能恢复或实际失败。

另一方面,使用Pooling=false将确保每个FbConnection.Open()都会创建一个新的物理连接,同样,FbConnection.ClearAllPools()将删除并关闭池中的现有物理连接,从而强制在后续调用FbConnection.Open()时需要新的物理连接。

现在,当创建此新的物理连接时,网络堆栈通常会非常快速地检测到远程服务器无法访问,并迅速失败,或者 - 如果网络连接已恢复 - 将能够快速连接。

不幸的是,Firebird ADO.net 提供程序似乎没有在其套接字上指定SendTimeoutReceiveTimeout,这意味着在没有工作套接字连接的情况下,无法使其更快地失败。

最新更新