¿Existe una diferencia de rendimiento al confirmar y revertir una transacción de solo lectura?

8

Abro una transacción (lectura repetible) ( BEGIN TRAN) para trabajar en ciertos registros. Lo primero que hago es verificar si los datos que necesito cambiar están en la base de datos. En algunos casos habrá y luego procedo a mis cambios. Pero en algunos casos no habrá nada que hacer. En este caso, COMMIT TRANo bien o ROLLBACK TRANy regreso del procedimiento almacenado. En este momento todavía no se realizaron cambios en los datos, por lo que el efecto de confirmación y reversión es el mismo.

¿Hay alguna consideración que debería tener en cuenta para elegir entre commit y rollback? ¿Hay un costo de rendimiento diferente? ¿Otras Consideraciones?

Andrew Savinykh
fuente

Respuestas:

10

Después de ejecutar esto a través de una sesión de depuración (para actualizar mi memoria defectuosa):

  • La reversión realiza más comprobaciones que una confirmación, pero no debería resultar en trabajo adicional o tener un efecto notable en el rendimiento en la situación que usted describe.
  • La transacción de lectura-escritura no comienza realmente a menos y hasta que se realice una modificación de datos.

Puede ver mucho de esto usando DMV, por ejemplo:

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

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

Salida:

Después de comenzar Tran

Después de seleccionar

Despúes de actualizar

Después de la transacción

Desde un punto de vista puramente práctico (como Aaron señaló en un comentario), probablemente sea más seguro emitir una reversión para garantizar que no se realicen cambios, en caso de que el código se modifique en el futuro. Entonces, todo se trata de intención: sin cambios = reversión.

De paso, REPEATABLE READes un nivel de aislamiento inusual para elegir; no siempre funciona como la gente esperaría intuitivamente . Dependiendo de sus requisitos, puede encontrar que el SNAPSHOTaislamiento es mejor.

Paul White 9
fuente