繁体   English   中英

使用 Oracle JDBC,如果我不 COMMIT select-only transactions 会遇到什么问题

[英]With Oracle JDBC, what problems will I face if I do not COMMIT select-only transactions

In order to connect to my Oracle DB, I use the thin Oracle JDBC driver and the tomcat JDBC connection pool.

默认设置tomcat-pool是在返回池时不去碰连接(任何关联的事务不提交也不回滚,实际的连接不关闭)。

Oracle 驱动的默认事务隔离级别为READ_COMMITTED ,自动提交设置为false

我有几种使用同一个连接池连接数据库的业务方法。 在某些业务方法中,我明确地创建一个新事务,发布一些更新并提交该事务。 到目前为止,一切都很好。

其他一些业务方法是只读的。 它们是只读的,因为我只发出SELECT查询,而不是因为我在连接上明确设置了READ ONLY模式(它保持关闭)。 我的理解是,在这些条件下,Oracle 在第一次遇到SELECT语句时会创建一个新的隐式事务,并保持该事务处于打开状态,直到我明确地COMMIT它。

但是,鉴于我只发出SELECT查询,我觉得没有必要提交事务。

我知道在将它们的连接返回到池之前不提交这些只读事务意味着下次从池中借用连接时,下一个业务方法将在之前已经启动的事务中执行。

我的问题是:

  • 有关系吗?
  • 鉴于事务隔离设置为READ_COMMITTED并且自动提交为false ,如果我提交只读事务,是否存在任何潜在的额外数据竞争条件?
  • 不提交事务是否会在数据库服务器端产生性能成本(事务可能会保持数小时未提交)?
  • 如果我们连接到 RAC 而不是单个 Oracle 数据库实例,上述问题的答案是否会改变?
  • 如果我从 DB Link 中选择呢?

从我读过的所有资源来看,到目前为止,我的结论是我所做的在技术上是不正确的,但只要我不选择更高的事务隔离级别也没关系。 READ_COMMITTED将读取其他事务最近提交的任何内容,无论当前事务是否已提交,并且 oracle 服务器上用于跟踪没有挂起修改的事务的开销是微不足道的。 所以解决这个问题属于“应该解决,但不是紧急情况”的范畴。

这有意义还是我误解了一些重要的事情?

就像 Alex Poole 评论的那样,数据库引擎确实不需要为某些读取操作的情况创建事务以进行正确操作。 我不熟悉 Oracle 内部结构,但我相信 Alex 在 select 查询之后运行查询将显示没有创建实际的 TX。

但是,数据库引擎是最低级别的,并且什么都知道。 除此之外,我们还有 DB 客户端程序,其中之一是 JDBC 驱动程序。 JDBC 有自己的标准,其中包括setAutocommit()类的东西,这是数据库不知道的东西,用于 JDBC 代码中的事务处理。 注意setAutocommit(false)是一个抽象,它并不意味着“开始事务”,它只是意味着操作将以某种方式分组到一个事务中。

这是 JDBC 与 DB 引擎差异开始的地方。 我基于 PostgreSQL 驱动程序代码(因为它更容易获得),但我希望 Oracle 驱动程序以类似的方式运行。

由于驱动程序无法轻易知道是否需要 TX,因此它无法像实际的 DB 引擎那样进行大量优化。 PostgreSQL 驱动程序有一个SUPPRESS_BEGIN标志,可用于指示不需要事务,即使以其他方式启动,但基于快速查看它仅在获取元数据时使用,该操作已知可避免事务问题. 否则,当autocommit=false时,即使对于SELECT ,驱动程序也会发出BEGIN来启动事务。

因此,即使 DB 引擎不需要 TX,驱动程序也是 DB 之上的抽象,与 JDBC 规范一起使用。 由于您已经观察到打开的事务,因此可以安全地假设 Oracle驱动程序还为 Oracle 数据库引擎不会创建隐式事务的操作创建显式事务。

那么,有关系吗?

正如评论中所讨论的,当您对本地表进行一些简单的选择时,可能不会有什么不同,因为事务不会占用大量资源。 但是加入数据库链接,随着时间的推移对查询的更改,并且存在非零风险。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM