Java 数据源的自动提交是否应设置为false?

Java 数据源的自动提交是否应设置为false?,java,mysql,oracle,transactions,datasource,Java,Mysql,Oracle,Transactions,Datasource,请参阅spring DataSourceTransactionManager.java中的注释,函数doBegin: // Switch to manual commit if necessary. This is very expensive in some JDBC drivers, // so we don't want to do it unnecessarily (for example if we've explicitly // configured the connection

请参阅spring DataSourceTransactionManager.java中的注释,函数doBegin:

// Switch to manual commit if necessary. This is very expensive in some JDBC drivers,
// so we don't want to do it unnecessarily (for example if we've explicitly
// configured the connection pool to set it already).
        if (con.getAutoCommit()) {
            txObject.setMustRestoreAutoCommit(true);
            if (logger.isDebugEnabled()) {
                logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
            }
            con.setAutoCommit(false);
        }
在我正在处理的项目中,未配置自动提交。因此,默认情况下这是正确的。我们使用Spring来管理事务,所有SQL都在@Transactional注释函数中执行。因此,事务实际上是手动提交的。每次事务开始时,db连接都会将autocommit设置为false,并在事务退出后将autocommit设置回true。典型的工作流是(在JDBC级别):

  • conn=dataSource.getConnection()
  • 连接设置自动提交(错误)
  • stmt=conn.createStatement()
  • 标准执行机构(…)
  • conn.commit()/conn.rollback()
  • conn.setAutoCommit(正确)
    来回设置自动提交是否昂贵?出于性能原因,是否应该将数据源连接池autocommit=false配置?要跳过步骤2和步骤6。

    在批量操作中,您可以在会话中将其设置为关闭,并在批量操作完成后再次设置为打开,以获得性能

    SET autocommit=0;
    your code here....
    SET autocommit=1;
    
    更新:

    正如@codemania很好地解释的那样,甚至可以根据您的要求禁用自动提交,但您不应该这样做。即使这是事务成功提交一组指令或回滚的基本需求,如果您这样做,那么您将如何实现它

    如果您正在执行一些繁重的任务,如数据迁移等,这将非常有用,因为您可以禁用自动提交以获得性能,但只能在该会话中使用。

    1)自动提交完全依赖于数据库,这意味着,通过连接的每条语句都将在一个单独的事务中执行,该事务是隐式执行的。除非和直到,您希望使用个人编码并避免这些锁被多个语句持有,这可能会导致与其他用户发生冲突,否则无需将自动提交设置为false

    2) 从性能的角度来看

    a)如果您有很多用户,并且由于持有数据库锁而发生冲突, 然后,可能需要检查与之相关的问题,但作为一个整体 自动提交规则的引入是为了简化初学者的工作。

    b)可能存在需要回滚的情况。

    c)您希望根据特定条件手动提交事务。

    编辑:我看到您已经编辑了这个问题,简单地回答您,autocommit=false将强制您编写自己的提交/回滚/etc,性能完全取决于数据库,实时持有的锁数

    否。再次将“自动提交”设置为false和true不会增加系统的使用费

    不,不要将数据源连接池autocommit=false配置,除非您是出于某种特定原因并且是有经验的人。从性能的角度来看,正如我已经指出的,它取决于数据库的类型和在实例中访问数据库的实时用户,对于您的项目,99.99%您不需要将其设置为false

    将autocommit设置为true只会确保在每个语句之后调用commit

    我还看到您是从数据源获取连接的,在这种情况下,最好将连接保留为默认设置,以便下次从池中获取连接时,工作流不会出现任何问题


    希望这有帮助

    无论何时发出数据库事务,都应该将autocommit设置为true。数据库传输是一个逻辑工作单元,通常由多个数据库操作(通常是多个更新)组成,您希望所有操作都成功,或者所有操作都失败。如果autocommit=false,在对连接对象调用commit()之前,您的更改不会持久化,因此这种方法可以保证所有更新要么成功,要么失败(在出现异常时调用rollback等)

    例如,当autocommit设置为true(默认值)时,您可以更改一个表,但在第二次更新(无论是更新/插入还是删除)时,可能会发生异常,并且您的第二个表不会得到更新,从而使数据库处于不一致的状态


    总之,当仅读取数据或数据库数据模型简单且只有少数用户访问时,autocommit=true是可以的(因此并发访问相同区域的数据非常罕见,甚至可以容忍某些数据库不一致)

    我猜这些set autocommit命令在我的测试中需要两次往返,每个事务额外花费0.8毫秒。在逻辑上,我认为,问题在于在保存各种语句的事务结束后,将autocommit设置为true时,因为您再次告诉系统返回默认状态并自行处理所有事情,而当您将autocommit设置为false时,情况并非如此,因此可能会有1次往返,而不是2次往返,这将花费您80万美元,如果您刚刚关闭连接,那么事情还取决于您在将autocommit设置为true之后所做的事情,这有什么关系D