【问题标题】:With Oracle JDBC, what problems will I face if I do not COMMIT select-only transactions使用 Oracle JDBC,如果我不 COMMIT select-only transactions 会遇到什么问题
【发布时间】:2021-02-18 15:12:48
【问题描述】:

为了连接到我的 Oracle DB,我使用了瘦 Oracle JDBC 驱动程序和 tomcat JDBC 连接池。

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

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

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

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

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

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

我的问题是:

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

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

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

【问题讨论】:

  • 我查看了其中一堆的代码,但默认情况下没有一个是这样做的。有些具有额外的设置,可让您配置自动提交或自动回滚。
  • 感谢您的链接。它的相关之处在于它提供了有关如何设置池以自行进行提交的线索。但是,它没有回答我提出的问题。我认为这些问题的答案很有趣,我找不到任何其他资源可以明确回答这些问题。此外,tomcat-pool 可以配置为在返回时提交事务,但它将无条件提交。这意味着在我已经提交 TX 的情况下,我将承担额外的、不必要的 DB 往返来提交空事务。
  • 您认为为什么会为select 创建事务?司机是在做自己的set transaction 电话吗?否则仅查询数据不应该启动事务。
  • 是的,显式启动的事务不会被隐式关闭。我怀疑你会遇到关键问题,但它仍然是一个令人讨厌的不确定性向量。我更担心未来的程序员错误,而不是数据库无法处理未提交的连接。或许您应该考虑一些措施来让开发人员更轻松地处理 tx?手动交易处理繁琐且容易出错。

标签: java oracle jdbc transactions


【解决方案1】:

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

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

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

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

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

那么,重要吗?

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-20
    • 2011-12-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多