【问题标题】:Best Practice for AutoCommit statements in Java for MySQL usage via JDBCJava 中 AutoCommit 语句的最佳实践,用于通过 JDBC 使用 MySQL
【发布时间】:2020-04-02 06:04:38
【问题描述】:

在我的 Java 代码中,我通过 JDBC 连接与 MySQL 数据库进行交互。我设置了一个连接和一些语句(用于重用)

            connect = DriverManager.getConnection(connectionstring);            
            statement = connect.createStatement();
            statement2 = connect.createStatement();

对于大多数代码, statement.executeQuery(query) 很好,但有些操作是“块”,所以我需要确保它们要么全部一起执行,要么都不执行。我相信下面的代码可以实现这一点。

            connect.setAutoCommit(false);
            statement.addBatch(insertquery1);
            statement.addBatch(insertquery2);
            statement.addBatch(insertquery3);
            statement.addBatch(insertquery4);
            statement.executeBatch();
            connect.commit();           
            connect.setAutoCommit(true);

据我所知,连接调用会影响整个连接,因此会影响语句和语句 2。此外,我似乎可以在创建语句对象之后设置 AutoCommit 值,它仍然适用于它。这个对吗?拆分它们并为自动提交调用保留不同的连接对象会更好/更有效吗?

            // objects purely for batch operations
            connect = DriverManager.getConnection(connectionstring);            
            connect.setAutoCommit(false);
            statement = connect.createStatement();
            // objects for normal operations
            connect2 = DriverManager.getConnection(connectionstring);           
            connect2.setAutoCommit(true);
            statement2 = connect2.createStatement();

在我的应用程序中,它们只占不到 1% 的调用,但这个百分比确实需要分批完成。最佳做法是什么?

【问题讨论】:

    标签: java mysql jdbc


    【解决方案1】:

    将自动提交设置为 false 的全部意义在于,多个 SQL 语句都可以在同一个事务中运行。而且,如果您的 4 个插入语句中的任何一个出现问题,整个事务将在逻辑上回滚,这样您就不会在数据库中出现不一致的数据。您已经遵循的模式是最佳实践:

    connect.setAutoCommit(false);
    statement.addBatch(insertquery1);
    statement.addBatch(insertquery2);
    statement.addBatch(insertquery3);
    statement.addBatch(insertquery4);
    statement.executeBatch();
    connect.commit();           
    connect.setAutoCommit(true);
    

    也就是说,最佳做法是在您完成事务后将自动提交恢复为真。这样一来,您的代码的任何其他部分,或者可能是您未来的代码,如果其他人继承它,仍然使用相同的连接对象,就会收到自动提交为 true 的默认行为。

    【讨论】:

    • 谢谢。问题是我是否应该将自动提交和正常查询分开到不同的连接中,例如出于性能原因?
    • 实际上,如果你真的关心性能,你应该考虑使用连接池,而不是原始的 JDBC 接口。当您在这里进行操作时,从头开始建立连接会产生很大的开销。话虽如此,如果您不能使用连接池,那么您应该避免为多个查询创建新连接,即对自动提交和非自动提交使用相同的连接。
    • 这就是我目前正在做的事情,我集中创建一个连接对象并分离出少量语句对象,然后通过其他地方的代码重用这些对象。个人更喜欢连接池,因为我可以手动管理语句(重新)使用。连接对象只创建一次,最长可存活 6 小时,因此启动时的小成本就可以了。
    • 那么,您问题另一部分的一般答案是避免创建新连接,因为这可能非常昂贵。如果您需要执行 1 个关闭自动提交的事务,以及 1 个打开自动提交的事务,请尽可能尝试使用相同的连接。
    • 我希望setAutocommit(false); 不做任何事情,而是设置一个标志,这将导致在执行下一条语句时发出BEGIN;,开始一个事务。虽然这将取决于驱动程序。但是setAutocommit(true); 在事务中will issue a commit
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-06-05
    • 1970-01-01
    • 1970-01-01
    • 2013-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多