Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Procedimentos armazenados aninhados contendo o padrão TRY CATCH ROLLBACK?


Este é o nosso modelo (registro de erros removido)

Este é projetado para lidar

Explicações:

  • todos os TXN begin e commit/rollbacks devem ser emparelhados para que @@TRANCOUNT é o mesmo na entrada e na saída

  • incompatibilidades de @@TRANCOUNT causar erro 266 porque

    • BEGIN TRAN incrementa @@TRANCOUNT

    • COMMIT decrementa @@TRANCOUNT

    • ROLLBACK retorna @@TRANCOUNT para zero

  • Você não pode diminuir @@TRANCOUNT para o escopo atual
    Isso é o que você acha que é a "transação interna"

  • SET XACT_ABORT ON suprime o erro 266 causado por @@TRANCOUNT incompatível
    E também lida com problemas como este "Tempo limite de transação do SQL Server" em dba.se

  • Isso permite TXNs do lado do cliente (como LINQ) Um único procedimento armazenado pode fazer parte de uma transação distribuída ou XA, ou simplesmente uma iniciada no código do cliente (digamos, .net TransactionScope)

Uso:
  • Cada proc armazenado deve estar em conformidade com o mesmo modelo

Resumo
  • Portanto, não crie mais TXNs do que você precisa

O código
CREATE PROCEDURE [Name]
AS
SET XACT_ABORT, NOCOUNT ON

DECLARE @starttrancount int

BEGIN TRY
    SELECT @starttrancount = @@TRANCOUNT

    IF @starttrancount = 0
        BEGIN TRANSACTION

       [...Perform work, call nested procedures...]

    IF @starttrancount = 0 
        COMMIT TRANSACTION
END TRY
BEGIN CATCH
    IF XACT_STATE() <> 0 AND @starttrancount = 0 
        ROLLBACK TRANSACTION;
    THROW;
    --before SQL Server 2012 use 
    --RAISERROR [rethrow caught error using @ErrorNumber, @ErrorMessage, etc]
END CATCH
GO

Observações:

  • A verificação de reversão é realmente redundante por causa de SET XACT_ABORT ON . No entanto, isso me faz sentir melhor, parece estranho sem e permite situações em que você não quer

  • Remus Rusanu tem um shell semelhante que usa pontos de salvamento. Eu prefiro uma chamada de banco de dados atômica e não uso atualizações parciais como o artigo deles