我想重命名数据库文件,甚至每次打电话时我都会使用using
连接:
FirebirdSql.Data.FirebirdClient.FbConnection.ClearAllPools();
问题是这个方法不会阻塞线程,我不知道如何检查是否清除了所有连接,因为如果我从中获取值:
FirebirdSql.Data.FirebirdClient.FbConnection.ConnectionPoolsCount
在方法之后立即为零,但我仍然无法重命名数据库文件。如果我在方法之后设置了一些超时(我尝试了1s),那么文件没有被锁定,我可以重命名它。问题是这个超时在不同的机器上肯定会有所不同。
FWIK唯一的另一种方法是如何检查文件是否未被锁定是尝试在循环中重命名一些超时,但我不能确定锁是由我的应用程序或其他地方的连接进行的。
那么有更好的方法,我可以等到这个方法清除连接吗?
答案 0 :(得分:4)
为了格式化列表而将其作为答案。
@Artholl你无法安全地依赖自己的断线连接。
可能还有其他程序已连接,而不仅仅是您正在运行的程序。除非您使用SYSDBA或数据库创建者或RDB $ ADMIN角色进行连接,否则无法立即查询是否存在其他连接。 但是,您可以从MON$ATTACHMENTS
查询与CURRENT_CONNECTION
相同的用户建立的连接。这可以帮助您检查应用程序自己的池的状态。只是它没有什么实际价值。
有LINGER参数,这意味着服务器会在最后一个客户端断开连接后保持数据库打开一段时间,期望如果某个新客户端可能决定再次连接,那么{数据库文件的{1}}已经存在。与中载WWW服务器一样。
即使在Firebird 2中,每个开放数据库都有一些缓存,它将是特定于安装(firebird.conf)和特定于数据库(gfix / gstat)的缓存有多大。在引擎看到所有客户端断开连接后决定关闭数据库 - 它首先刷新缓存并要求操作系统刷新缓存(没有通用的硬件独立方式来要求RAID控制器和磁盘本身刷新缓存,或者Firebird也会尝试制作它。默认情况下,Firebird缓存很小,抢占它们到硬件层应该很快,但它仍然不是即时的。
即使您检查了所有其他客户端已断开连接,然后您自行断开连接,然后您正确猜到等待Linger和Caches需要多长时间即便如此,你仍然不安全。您受竞争条件的约束。在你开始做一些需要明确拥有DB的事情的时候,可能会发生一些同时打开他的新连接的新客户端。
因此,正确的方法不仅仅是证明现在没有数据库连接,而且还要确保将来不再有任何新连接,直到您重新启用它。
因此,正如Mark上面所说,您必须使用Shutdown方法将数据库置于无连接允许状态。在您完成文件重命名和其他操作之后 - 将其切换回正常模式。
答案 1 :(得分:3)
如果我负责维护firebird提供者,我不希望用户依赖这样的功能。
其他应用程序可能打开文件(您只能控制当前AppDomain
中的连接池),并且服务器可能正在对数据库运行某种维护。
所以,即使你可以等待清除池,我也会争辩说,如果你真的不得不弄乱这些文件,一个更强大的解决方案是停止firebird服务而不是(并等待它完全停止)。