Есть ли разница в производительности при фиксации и откате транзакции только для чтения?

8

Я открываю (повторяемое чтение) транзакцию ( BEGIN TRAN), чтобы выполнить некоторую работу с определенными записями. Первое, что я делаю, это проверяю, находятся ли данные, которые мне нужно изменить, в базе данных. В некоторых случаях будет, и тогда я перейду к своим изменениям. Но в некоторых случаях делать нечего. В этом случае я либо COMMIT TRANили ROLLBACK TRANвозвращаюсь из хранимой процедуры. В настоящее время в данные еще не было внесено никаких изменений, поэтому эффект фиксации и отката одинаков.

Есть ли какие-то соображения, которые я должен знать о выборе между фиксацией и откатом? Есть ли разница в производительности? Другие соображения?

Андрей Савиных
источник

Ответы:

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

Вывод:

После начала тран

После выбора

После обновления

После транзакции

С чисто практической точки зрения (как заметил Аарон в комментарии), вероятно, безопаснее выполнить откат, чтобы гарантировать отсутствие изменений в случае, если код будет изменен в будущем. Итак, все дело в намерениях: без изменений = откат.

Попутно, REPEATABLE READэто необычный уровень изоляции на выбор; это не всегда работает, как люди ожидают интуитивно . В зависимости от ваших требований, вы можете найти SNAPSHOTизоляцию лучше.

Пол Уайт 9
источник