为什么使用FirebirdAutocommit=true不起作用,另外禁用JDBC自动提交



我用来连接Firebird:

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,速度非常快(大约每秒1000次更新)。

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

如文档中所述,当您启用useFirebirdAutocommit选项时,则:

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

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

然而,使用commit retain有缺点:因为它保留了原始事务句柄,它将固定原始事务和它感兴趣的事务,导致垃圾收集被抑制,直到事务句柄真正提交。此外,当使用非read committed事务隔离级别时,它不会改变可见记录集。

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

这是这个特性被标记为实验性的主要原因,也是为什么文档中说:

对该选项的支持是实验性的,应该只在以下情况下启用您1)知道自己在做什么,并且2)确实需要这个功能。内部isc_tpb_autocommit使用commit_retaining,这意味着使用此功能可能会增加与关联的扫描和垃圾收集影响。

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

如果你坚持使用这个特性,那么确保你的连接是短暂的(例如减少最大连接寿命,DBCP属性maxConnLifetimeMillis),或者你通过禁用(和启用)自动提交来定期强制一次真正的提交。

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

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

声明:我是Jaybird

的维护者。

相关内容

  • 没有找到相关文章

最新更新