【问题标题】:Should I be using SQL transactions, while reading records?我应该在读取记录时使用 SQL 事务吗?
【发布时间】:2011-03-06 07:59:52
【问题描述】:

SQL事务用于插入、更新,但它应该用于读取记录吗?

【问题讨论】:

  • 感谢所有回答者,我希望可以选择将所有内容标记为答案,但没有。感谢您提供示例,提供锁定解释的链接,以及如何以毫秒为单位更新数据的解释,谢谢。

标签: c# sql sql-server-2005


【解决方案1】:

可以进行交易,但其目的是什么?

您可以使用 SET TRANSACTION ISOLATION LEVEL 语句为整个 SQL Server 会话设置适当的隔离级别。

这是 SQL Server 联机丛书中的语法:

SET TRANSACTION ISOLATION LEVEL 
    {
        READ COMMITTED 
        | READ UNCOMMITTED 
        | REPEATABLE READ 
        | SERIALIZABLE
    }

Locking in Microsoft SQL Server.

【讨论】:

    【解决方案2】:

    纯读取不需要事务包装。

    在您的 SQL 语句中,锁定提示应注意向您返回正确的数据 (http://msdn.microsoft.com/en-us/library/aa213026%28SQL.80%29.aspx)。

    在服务器级别,您可以设置事务隔离级别 (http://msdn.microsoft.com/en-us/library/ms173763.aspx)。

    编辑

    解释纯读

    如果你所有的 SQL 语句都有这些类型的读取,那么你不需要包装在事务中

    SELECT Col1, Col2
    From Table1
        INNER JOIN Table2
            ON Table1.Id = Table2.Table1Id
    

    如果您正在读取可能受其他并行事务影响的结果,那么您必须包装在一个事务中。例如:

    BEGIN TRANSACTION
    
    INSERT INTO AccountTransactions (Type, Amount) Values ('Credit', 43.21)
    UPDATE AccountSummary SET Balance = Balance + 43.21
    
    SELECT @Balance = Balance FROM AccountSummary
    
    COMMIT TRANSACTION
    

    确实,您只是退回余额,但整个货币交易必须在两个地方进行。

    【讨论】:

    • 在以下示例中,任何并发进程都可能干扰您正在读取的表。没有数据的写入,但是相关的读取之间有计算。因此,需要一个 TRANSACTION 来保护数据的状态。插入@temp SELECT ; ;选择 ;
    • 这不是纯粹的阅读。 Raj 说“纯读取不需要事务包装。”
    • 定义“纯读”,我给出的示例除了变量之外没有插入、更新或删除任何内容。 [它可以是一个 INT、一个表变量或其他一些数据容器,以方便计算,然后定义最终读取的行为]
    • 您正在修改结构调用@temp。这是一个 INSERT 语句,而不是纯读取,特别是如果您的 @temp 用于随后的 SELET <blah> 语句中。
    • 但是从黑盒的角度来看,数据库中没有任何变化。例如,临时变量可以在用户定义的函数中使用。根据您对“纯读”的定义,您甚至不能使用 INT 变量,因此我认为您仅限于单个 SQL 语句。我会说“纯阅读”实际上描述了一个不会对数据库或其内容造成(临时或永久)更改的过程,无论它们对任何其他进程可见还是不可见。在我看来,要求甚至不使用变量描述了一个过于琐碎的场景。
    【解决方案3】:

    当一个逻辑事务实际上映射到多个 SQL 查询时,事务旨在避免并发问题。例如,对于银行账户,如果您将资金从一个账户转移到另一个账户,您将首先从账户中减去金额,然后将其添加到另一个账户(反之亦然)。但是,如果在您的数据库之间发生一些错误,您的数据库将处于无效状态(您可能已经从一个帐户中减去了金额,但没有将其添加到另一个帐户)。因此,如果您在一个查询中读取所有数据,则不需要事务。

    【讨论】:

      【解决方案4】:

      当您在事务中修改了某些内容时,您可以在提交之前使用 read 语句检查操作是否生效。

      【讨论】:

        【解决方案5】:

        不,读取数据通常不需要事务,它也会减慢您的数据读取速度。

        我建议您阅读 ATOMIC 一词。这将帮助您了解交易的用途。

        【讨论】:

          【解决方案6】:

          如果您在单个查询中查询所有记录,然后一次性将它们拉回,则没有必要。一切都包含在隐式事务中。也就是说,即使你取回了 100 万条记录,即使其他进程正在更改记录,你也会看到所有 100 万条记录在同一时间点的样子。

          在只读进程中真正需要事务(通常还需要特定的锁定提示)的唯一情况是:
          - 您阅读记录“零碎”并且在迭代时不需要其他任何东西来更改值。 [例如 ADO 中连接的记录集,然后您将光标通过。]
          - 您读取了一些数据,进行了一些计算,然后读取了一些相关数据,但假设同时没有任何变化。


          简而言之,当您希望阻止其他进程在 SQL 语句之间干扰您的数据时,您需要事务。

          【讨论】:

            【解决方案7】:

            如果您需要最新的毫秒信息,您可以使用由TransactionOptions 构造的事务,该事务具有IsolationLevelSerializable

            这会影响性能,因为它会锁定表(或表的一部分),所以你需要弄清楚你是否真的需要这个。

            对于大多数用途,如果您正在执行读取操作,则不需要围绕它包装事务(假设您只在一个操作中执行读取操作)。

            这实际上取决于您的应用程序、它需要什么数据以及如何使用它。

            例如,如果您进行读取并根据结果进行写入或更新,但您刚刚读取的数据是最新的至关重要,您可能应该将整个逻辑包装到单个事务中。

            【讨论】:

              猜你喜欢
              • 2015-09-19
              • 2022-01-05
              • 1970-01-01
              • 2012-12-31
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2014-10-21
              • 1970-01-01
              相关资源
              最近更新 更多