CommitRetaining 导致 Firebird 数据库不断增长?

ral*_*iii 3 delphi firebird commit

我们有用户报告 Firebird 数据库对于我们应用程序存储的条目数量来说太大了。

我发现一篇文章 Commit vs CommitRetaining 表明使用 CommitRetaining 并不是最明智的做法,并且可能会阻止 GarbageCollection 工作。

我们的软件由多个应用程序组成,所有应用程序都连接到 Firebird 数据库。有些与某些用户操作绑定并且仅运行几秒钟或几分钟,其他则是可以运行数月的后台应用程序。

因为我认为 CommitRetaining 与 Commit “一样好”,而且我不必小心地启动新事务,所以我在任何地方都使用 CommitRetaining。

现在我想知道,我是否需要让所有应用程序都没有 CommitRetaining,或者是否足够,长时间运行的应用程序是否“干净”,而短时间运行的应用程序并不重要,因为当它们关闭时,这才算作无论如何都要提交?

而且,只是因为我很好奇:Firebird 是否需要使用 CommitRetaining 释放任何连接来执行 GC,或者每个连接都单独处理。

换句话说:假设 2 个应用程序 A 和 B 正在运行

AAAA--AAAA--AAAA-....
---BBBB--BBBB--B...
Run Code Online (Sandbox Code Playgroud)

那么 A 或 B 总是连接到 DB,这会永远阻止 GC 吗?

Mar*_*eel 7

使用提交保留提交的事务实际上不会结束,直到它真正提交为止,这意味着最旧的有趣事务和最旧的活动事务实际上被冻结,并且这抑制了记录版本的大部分垃圾收集,因为它们可能仍然是有趣的到最旧的活动事务。保留的时间越长,累积的旧版本就越多,这会占用空间并降低性能。

垃圾收集的抑制并不依赖于连接本身(事实上,如果没有活动连接读取数据页,Firebird 不会收集垃圾)。它取决于尚未真正提交的连接的一个或多个活动事务句柄,仅保留提交(或回滚)。因此,一旦您切换到使用正常提交,或者通过定期使用真正的提交而不是提交保留来减少事务的生存时间,垃圾收集应该能够继续进行。

然而,只要您使用提交保留,您可能会比在各处切换到真正的提交积累更多的垃圾。

换句话说,将长时间运行的应用程序切换为使用真正的提交应该可以缓解数据库增长带来的大部分问题。