代码之家  ›  专栏  ›  技术社区  ›  dcp

jdbc-setautocommit用于只读操作

  •  7
  • dcp  · 技术社区  · 15 年前

    假设我有一个创建DB连接的公共方法:

    Connection getConnection() throws SQLException {
        Connection con = ... // create the connection
        con.setAutoCommit(false);
        return con;
    }
    

    我把 setAutoCommit(false) 在此调用,以便此方法的调用方不必担心设置它。但是,如果调用者执行的操作只是读取数据,那么这是一个坏做法吗?有额外的开销吗?

    我个人的观点是,最好将逻辑集中在一个地方,这样调用方就不必设置自动提交,这样就避免了代码冗余。我只是想确保它不会为只读操作带来任何不必要的开销。

    4 回复  |  直到 11 年前
        1
  •  5
  •   Pascal Thivent    15 年前

    我把setautocommit(false)调用放在这里,这样这个方法的调用方就不必担心设置它了。

    这是很好的IMO,我个人认为永远不应该在应用程序中启用自动提交模式。所以我的建议是关闭自动提交。

    但是,如果调用者执行的操作只是读取数据,那么这是一个坏做法吗?有额外的开销吗?

    从严格的性能角度来看,对于每个有开销并且可能降低应用程序性能的SQL语句,它都在启动和结束数据库事务。

    顺便说一下,select语句受 setAutoCommit(boolean) 根据JavaDoc:

    设置此连接的自动提交 模式到给定状态。 如果A 连接处于自动提交模式, 那么它的所有SQL语句都将 作为个人执行和承诺 交易 . 否则,它的SQL 语句分组为 被终止的交易 调用方法commit或 方法回滚。默认情况下,新建 连接处于自动提交模式。

    当语句 完成。 陈述的时间 完成取决于SQL的类型 声明:

    • 对于DML语句,例如insert、update或delete和ddl语句, 声明一经完成 它已完成执行。
    • 对于select语句,当关联的结果 集合已关闭。
    • 对于CallableStatement对象或返回多个 结果,陈述是完整的 当所有关联的结果集 已关闭,所有更新 计数和输出参数 恢复。
        2
  •  5
  •   BalusC    15 年前

    自动提交没有任何值 SELECT 查询。但是关闭自动提交确实是一种更常见的做法。您经常希望在事务中触发查询。默认情况下,大多数连接池也会将其关闭。不过,我建议将其设置为连接管理器的配置设置和/或使用布尔参数重载方法,这样至少可以 任何 在这种情况下控制它。

        3
  •  3
  •   beldaz Nicolas W.    11 年前

    这是一个古老的问题,但我想对这个问题给出不同的意见。

    性能

    事务的性能开销随并发控制机制而变化:通常是多版本并发控制或锁定。其他答案中表达的关注点似乎是结束事务的成本,但根据我的经验,最大的痛苦是长时间运行的事务,这可能导致性能瓶颈。例如,如果DBMS使用锁定,则在终止涉及该表的事务之前,无法更新表的某些部分。在诸如Oracle这样的系统中,更令人沮丧的是DDL操作( ALTER TABLE 等)必须等待,直到使用该表的所有事务都结束,从而导致麻烦的超时。所以如果你只是使用 SELECT S.

    习俗

    关闭自动提交行为的一个微妙问题是,您正在从默认值进行更改,因此使用您的代码的任何其他人都可能没有预料到这一点。它是 真的很容易 通过一个函数留下一个意外的路径,而不是以一个显式的 commit rollback ,这会导致随后调用的函数中出现不可预测的行为。相反,我看到的大部分DB接口代码在每个函数中都包含一条语句,对于这些语句,自动提交行为非常适合。事实上,我遇到的许多多语句函数可以被重新编写为单个语句,而SQL语句则更多一些——在Java中实现对连接的差近似是很常见的。

    基于合理的经验,我个人对调用数据库的任何函数的偏好如下:

    • 保持自动提交打开的默认JDBC行为;
    • 当函数包含多个SQL语句时,通过设置 setAutocommit(false) 在每个函数和调用开始时 commit() (或) rollback() 如果合适的话)在最后,理想情况下 回滚() catch 街区;
    • 通过将 setAutocommit(true) finally 在函数中包装JDBC调用的块(与PHP/PDO等API不同,JDBC在 提交() / 回滚() ;
    • 如果你有额外的防御性,明确选择 设置自动提交(真) 设置自动提交(错误) 在每个功能开始时;
        4
  •  1
  •   Nivas    15 年前

    在应用程序的任何地方,我都不会将autocommit设置为true。 性能开销(如果有的话)与侧边相比是零 A的影响 autocommit=true 连接。

    你说你永远不会把这个连接用于DML。但这就是 意图 可能通过编码标准等来维护,但实际上 可以将此连接用于DML语句。这足够我从不设置自动提交的理由了。

    Select 语句肯定会占用一些内存/cpu/网络。让autocommit的开销成为每个select语句的固定开销(非常边际),以确保应用程序的数据完整性和稳定性。

    推荐文章