我应该提交还是回滚读取事务?

Ste*_*ser 91 sql database transactions

我有一个读取查询,我在一个事务中执行,以便我可以指定隔离级别.查询完成后,我该怎么办?

  • 提交交易
  • 回滚事务
  • 什么也不做(这将导致事务在使用块结束时回滚)

做每一个有什么含义?

using (IDbConnection connection = ConnectionFactory.CreateConnection())
{
    using (IDbTransaction transaction = connection.BeginTransaction(IsolationLevel.ReadUncommitted))
    {
        using (IDbCommand command = connection.CreateCommand())
        {
            command.Transaction = transaction;
            command.CommandText = "SELECT * FROM SomeTable";
            using (IDataReader reader = command.ExecuteReader())
            {
                // Read the results
            }
        }

        // To commit, or not to commit?
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑:问题不在于是否应该使用交易或是否有其他方法来设置交易级别.问题是,是否提交或回滚了不修改任何内容的事务.有性能差异吗?它会影响其他连接吗?还有其他差异吗?

Mar*_*ett 50

你提交.期.没有其他合理的选择.如果您开始了交易,则应该关闭它.提交释放您可能拥有的任何锁,并且对ReadUncommitted或Serializable隔离级别同样敏感.依赖隐式回滚 - 虽然技术上可能等同 - 只是糟糕的形式.

如果这还没有说服你,那么想象下一个在代码中间插入更新语句的人,并且必须追踪发生的隐式回滚并删除他的数据.

  • 有一个明智的选择 - 回滚.显式回滚,即.如果您不想改变任何内容,则回滚可确保撤消任何操作.当然,不应该有任何改变; rollback保证. (40认同)
  • 假设我创建了一个临时表,用ids填充它,用数据表连接它以选择与ids一起使用的数据,然后删除临时表.我真的只是在读数据,我不关心临时表会发生什么,因为它是临时的......但从性能的角度来看,回滚事务或提交它会更昂贵吗?除了临时表和读操作之外什么都没有提交/回滚的效果? (7认同)
  • @Triynko - 直觉上,我猜ROLLBACK更贵.COMMIT是正常用例,ROLLBACK是例外情况.但是,除了学术上,谁在乎呢?我相信你的应用程序有1000个更好的优化点.如果您真的很好奇,可以在http://bazaar.launchpad.net/~mysql/mysql-server/mysql-6.0/annotate/head:/sql/transaction.cc找到mySQL事务处理代码. (4认同)
  • @Triynko - 优化的*唯一方法是分析.这是一个如此简单的代码更改,如果你真的想要优化它,没有理由不分析这两种方法.请务必向我们提供结果! (3认同)
  • 不同的DBMS可以具有不同的"隐式事务完成"语义.IBM Informix(我相信DB2)做隐式回滚; 通过谣言,Oracle做了一个隐含的提交.我更喜欢隐式回滚. (2认同)
  • @标记。这是一个优化点,因此我对其进行了优化。它被足够频繁地调用(作为用户规模的问题,而不是应用程序设计),它需要尽可能快。直觉上,人们会认为回滚更昂贵......但这取决于数据库如何提交事务与回滚它,这就是我问的原因。例如,回滚可以简单地丢弃在内存中完成的工作,而提交可能会更改数据库统计信息或其他内容。 (2认同)

Gra*_*row 25

如果您没有更改任何内容,则可以使用COMMIT或ROLLBACK.任何一个都会释放你已经获得的任何读锁定,并且由于你没有做任何其他更改,它们将是等效的.

  • 感谢您让我知道它们是等效的。在我看来,这最好地回答了实际问题。 (3认同)

Nei*_*ell 6

如果您开始交易,那么最佳做法始终是提交.如果在您的use(事务)块中抛出异常,则事务将自动回滚.


Kla*_*aws 5

考虑嵌套事务

大多数 RDBMS 不支持嵌套事务,或者尝试以非常有限的方式模拟它们。

例如,在 MS SQL Server 中,内部事务(这不是真正的事务,MS SQL Server 只是计算事务级别!)中的回滚将回滚最外层事务(这是真正的事务)中发生的所有事情。

某些数据库包装器可能会将内部事务中的回滚视为发生错误的标志,并回滚最外层事务中的所有内容,无论最外层事务是提交还是回滚。

因此,当您无法排除您的组件被某些软件模块使用时,COMMIT 是安全的方法。

请注意,这是对该问题的一般性回答。该代码示例通过打开新的数据库连接巧妙地解决了外部事务的问题。

关于性能:根据隔离级别,SELECT 可能需要不同程度的 LOCK 和临时数据(快照)。当交易关闭时,这将被清除。这是通过 COMMIT 还是 ROLLBACK 完成的并不重要。所花费的 CPU 时间可能存在微不足道的差异 - COMMIT 的解析速度可能比 ROLLBACK 更快(少两个字符)以及其他细微差异。显然,这只适用于只读操作!

完全没有要求:另一个可能阅读代码的程序员可能会认为回滚意味着错误情况。