提交和回滚只读事务是否存在性能差异?

And*_*ykh 8 sql-server transaction

我打开一个(可重复读)事务 ( BEGIN TRAN) 对某些记录做一些工作。我做的第一件事是检查我需要更改的数据是否在数据库中。在某些情况下,会有然后我继续我的更改。但在某些情况下,将无事可做。在这种情况下,我要么COMMIT TRANROLLBACK TRAN从存储过程返回。此时还没有对数据做任何改动,所以commit和rollback的效果是一样的。

在提交和回滚之间进行选择时,我应该注意什么?是否有不同的性能成本?其他考虑?

Pau*_*ite 10

通过调试会话运行它(刷新我失败的记忆):

  • 回滚比提交执行更多检查,但在您描述的情况下,它不应导致额外的工作或对性能产生明显影响。
  • 除非进行数据修改,否则读写事务不会真正开始。

您可以使用 DMV 看到大部分内容,例如:

-- Temporary procedure to show the state of the transaction
CREATE PROCEDURE #TranState
    @Comment varchar(100)
AS
BEGIN
    SELECT 
        @Comment AS Comment,
        DTCT.transaction_id,
        database_name =
            CASE DTDT.database_id
                WHEN 32767 THEN N'resource'
                ELSE DB_NAME(DTDT.database_id)
            END,
        tran_begin_time = DTDT.database_transaction_begin_time,
        tran_type =
            CASE DTDT.database_transaction_type
                WHEN 1 THEN 'read/write'
                WHEN 2 THEN 'read only'
                WHEN 3 THEN 'system'
            END,
        tran_state =
            CASE DTDT.database_transaction_state
                WHEN 1 THEN 'The transaction has not been initialized.'
                WHEN 3 THEN 'The transaction has been initialized but has not generated any log records.'
                WHEN 4 THEN 'The transaction has generated log records.'
                WHEN 5 THEN ' The transaction has been prepared.'
                WHEN 10 THEN 'The transaction has been committed.'
                WHEN 11 THEN 'The transaction has been rolled back.'
                WHEN 12 THEN 'The transaction is being committed. In this state the log record is being generated, but it has not been materialized or persisted.'
            END
    FROM sys.dm_tran_current_transaction AS DTCT
    JOIN sys.dm_tran_database_transactions AS DTDT
        ON DTDT.transaction_id = DTCT.transaction_id;
END;
Run Code Online (Sandbox Code Playgroud)

AdventureWorks 上的测试:

SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;

BEGIN TRANSACTION;

EXECUTE dbo.#TranState @Comment = 'After Begin Tran';

SELECT TOP (1)
    P.Name
FROM Production.Product AS P
ORDER BY 
    P.Name;

EXECUTE dbo.#TranState @Comment = 'After Select';

UPDATE Production.Product
SET Name = N'New Blade'
WHERE Name = N'Blade';

EXECUTE dbo.#TranState @Comment = 'After Update';

-- Or Commit
ROLLBACK TRANSACTION;

EXECUTE dbo.#TranState @Comment = 'After Tran';
Run Code Online (Sandbox Code Playgroud)

输出:

开始 Tran 之后

选择后

更新后

交易后

从纯粹实用的角度来看(正如 Aaron 在评论中指出的那样),发出回滚以保证不进行任何更改可能更安全,以防将来修改代码。所以,这一切都与意图有关:没有变化 = 回滚。

顺便说REPEATABLE READ一下,是一个不寻常的隔离级别可供选择;它并不总是如人们直觉所期望的那样工作。根据您的要求,您可能会发现SNAPSHOT隔离更合适。