我打开(可重复读取)事务(BEGIN TRAN
),对某些记录进行一些处理。我要做的第一件事是检查我需要更改的数据是否在数据库中。在某些情况下,我会进行更改。但是在某些情况下,这无关紧要。在这种情况下,我要么COMMIT TRAN
还是ROLLBACK TRAN
和返回从存储过程。目前,尚未对数据进行任何更改,因此提交和回滚的效果是相同的。
我应该在提交和回滚之间选择任何考虑因素吗?有不同的性能成本吗?其他考虑因素?
我打开(可重复读取)事务(BEGIN TRAN
),对某些记录进行一些处理。我要做的第一件事是检查我需要更改的数据是否在数据库中。在某些情况下,我会进行更改。但是在某些情况下,这无关紧要。在这种情况下,我要么COMMIT TRAN
还是ROLLBACK TRAN
和返回从存储过程。目前,尚未对数据进行任何更改,因此提交和回滚的效果是相同的。
我应该在提交和回滚之间选择任何考虑因素吗?有不同的性能成本吗?其他考虑因素?
Answers:
通过调试会话运行此命令(以刷新失败的内存):
您可以使用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';
输出:
从纯粹的实际角度来看(如Aaron在评论中指出的那样),如果将来要修改代码,发出回滚以保证不进行任何更改可能更安全。因此,这全都与意图有关:无更改=回滚。
顺便说一句,REPEATABLE READ
是一个不寻常的隔离级别可供选择;人们总是凭直觉期望并不总是可行的。根据您的要求,您可能会发现SNAPSHOT
隔离更合适。