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


8

我打开(可重复读取)事务(BEGIN TRAN),对某些记录进行一些处理。我要做的第一件事是检查我需要更改的数据是否在数据库中。在某些情况下,我会进行更改。但是在某些情况下,这无关紧要。在这种情况下,我要么COMMIT TRAN还是ROLLBACK TRAN和返回从存储过程。目前,尚未对数据进行任何更改,因此提交和回滚的效果是相同的。

我应该在提交和回滚之间选择任何考虑因素吗?有不同的性能成本吗?其他考虑因素?

Answers:


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;

在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';

输出:

开始之后Tran

选择后

更新后

交易后

从纯粹的实际角度来看(如Aaron在评论中指出的那样),如果将来要修改代码,发出回滚以保证不进行任何更改可能更安全。因此,这全都与意图有关:无更改=回滚。

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.