【问题标题】:Why useFirebirdAutocommit=true won't work and additionally disable JDBC autocommit为什么 useFirebirdAutocommit=true 不起作用并另外禁用 JDBC 自动提交
【发布时间】:2021-10-23 18:17:12
【问题描述】:

我用来连接火鸟:

org.apache.commons.dbcp2.BasicDataSource;

但如果我设置:

ds.addConnectionProperty("autoCommit", "true");
ds.addConnectionProperty(FBConnectionProperties.USE_FIREBIRD_AUTOCOMMIT, "true");

ds.addConnectionProperty("useFirebirdAutocommit", "true");

自动提交根本不起作用。只有在我不使用 "useFirebirdAutocommit" 属性时才有效。

或者如果我添加 isc_tpb_autocommit 它也可以:

ds.addConnectionProperty("TRANSACTION_READ_COMMITTED", "isc_tpb_read_committed,"+
                "isc_tpb_rec_version,isc_tpb_write,isc_tpb_wait,**isc_tpb_autocommit**");

似乎使用了内部服务器自动提交,驱动程序禁用自动提交,但内部服务器自动提交不起作用。

顺便说一句 - 结果,我确信我有自动提交 - 但每次更新都会创建另一个版本的记录,其中未提交的事务无法被清除。数据库文件从 3MB 快速增长到 15GB 几天 24/7(大约每秒 1000 次更新)。

【问题讨论】:

  • 请提供minimal reproducible example 并描述您遇到的确切问题。而且,如文档中所述,useFirebirdAutoCommit 选项是实验性的(可能会一直如此)。它有一些严重的缺点,包括固定事务,这确实会阻碍垃圾收集。
  • 另外请解释“自动提交不起作用”(如:数据对其他事务不可见吗?)。如果实际问题是您的数据库的增长,那么这正是因为您正在使用useFirebirdAutocommit 和长时间运行的连接。使用useFirebirdAutoCommit实际上不会提交事务句柄,并且由于其内部机制,这意味着垃圾收集被禁止,这对于持续处于自动提交模式的长期连接来说尤其痛苦。

标签: java jdbc firebird autocommit jaybird


【解决方案1】:

在这个答案中,我假设记录版本和文件大小的增长是您遇到的唯一问题。如果不是这种情况,请更新您的问题并提供问题的更多详细信息。

documentation 中所述,当您启用useFirebirdAutocommit 选项时,则:

Jaybird 本身不会提交,直到连接关闭(或切换到 autoCommit=false)。

换句话说,当启用useFirebirdAutocommit 时,驱动程序不会在自动提交中提交这一事实是此功能的预期行为(事实上,这是它存在的全部理由)。相反,服务器将在每个执行语句之后在内部执行commit retain,同时保留事务句柄。这将使更改对其他事务可见,同时避免额外网络往返的开销。

但是,commit retain 的使用也有缺点:因为它保留了原始事务句柄,所以会锁定原始事务和它感兴趣的事务,导致垃圾收集被禁止,直到事务句柄被实际提交。另外,当使用读提交以外的事务隔离级别时,不会改变可见记录集。

因此,如果您将它与从不使用实际事务的长时间运行的连接一起使用(即您从不禁用自动提交),您将在很长一段时间内禁止垃圾收集。如果你有很多更新,这确实会导致记录版本和数据库文件本身的极端增长。

这是此功能被标记为实验性的主要原因,也是文档说的原因:

对此选项的支持是实验性的,仅应在以下情况下启用 你 1) 知道你在做什么,并且 2) 真的需要这个功能。 在内部isc_tpb_autocommit 使用commit_retaining,这意味着 使用此功能可能会增加交易差距 相关的清除和垃圾收集影响。

除非您使用短期连接,或者定期在启用和禁用自动提交之间切换,否则您不应该使用useFirebirdAutocommit 模式。

如果您确实坚持使用此功能,请确保您的连接是短暂的(例如,减少最大连接寿命,DBCP 属性maxConnLifetimeMillis),或者您定期通过禁用(并启用) 自动提交。

这些缺点是此功能是实验性的原因,并且可能会一直如此。

至于为什么重新定义 TRANSACTION_READ_COMMITTED 确实(似乎)有效,是因为 - 假设 useFirebirdAutocommit 未启用 - 在每个语句完成后驱动程序仍将真正提交自动提交事务。当您只使用自动提交时手动将isc_tpb_autocommit 添加到事务定义中几乎没有好处(实际上,由于内部commit retain 和实际提交,它的开销略高)。

免责声明:我是 Jaybird 的维护者

【讨论】:

    猜你喜欢
    • 2017-11-05
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    • 1970-01-01
    • 1970-01-01
    • 2011-09-11
    • 1970-01-01
    • 2011-04-14
    相关资源
    最近更新 更多