Gibt es einen Leistungsunterschied beim Festschreiben und Zurücksetzen einer schreibgeschützten Transaktion?

8

Ich öffne eine (wiederholbare Lese-) Transaktion ( BEGIN TRAN), um bestimmte Datensätze zu bearbeiten. Als erstes überprüfe ich, ob sich die Daten, die ich ändern muss, in der Datenbank befinden. In einigen Fällen wird es geben und dann gehe ich zu meinen Änderungen über. In einigen Fällen gibt es jedoch nichts zu tun. In diesem Fall kehre ich entweder COMMIT TRANoder ROLLBACK TRANund von der gespeicherten Prozedur zurück. Zu diesem Zeitpunkt wurden noch keine Änderungen an den Daten vorgenommen, sodass die Auswirkungen von Commit und Rollback gleich sind.

Gibt es Überlegungen, die ich beachten sollte, um zwischen Commit und Rollback zu wählen? Gibt es unterschiedliche Leistungskosten? Weitere Überlegungen?

Andrew Savinykh
quelle

Antworten:

10

Nachdem Sie dies durch eine Debugging-Sitzung ausgeführt haben (um meinen fehlerhaften Speicher zu aktualisieren):

  • Rollback führt mehr Überprüfungen durch als ein Commit, sollte jedoch in der von Ihnen beschriebenen Situation keine zusätzliche Arbeit verursachen oder die Leistung spürbar beeinträchtigen.
  • Die Lese- / Schreibtransaktion beginnt erst dann wirklich, wenn eine Datenänderung vorgenommen wurde.

Sie können viel davon mit DMVs sehen, zum Beispiel:

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

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

Ausgabe:

Nach Beginn Tran

Nach Auswahl

Nach dem Update

Nach der Transaktion

Aus rein praktischer Sicht (wie Aaron in einem Kommentar feststellte) ist es wahrscheinlich sicherer, ein Rollback durchzuführen, um sicherzustellen, dass keine Änderungen vorgenommen werden, falls der Code in Zukunft geändert wird. Es geht also nur um Absicht: keine Änderungen = Rollback.

Im Vorbeigehen REPEATABLE READist eine ungewöhnliche Isolationsstufe zu wählen; Es funktioniert nicht immer so, wie es die Leute intuitiv erwarten würden . Abhängig von Ihren Anforderungen ist SNAPSHOTIsolation möglicherweise besser geeignet.

Paul White 9
quelle