Usar transações com o pool de SQL dedicado no Azure Synapse Analytics
Dicas para implementar transações com o pool de SQL dedicado no Azure Synapse Analytics para desenvolver soluções.
O que esperar
Como era esperado, o pool de SQL dedicado suporta transações como parte da carga de trabalho do data warehouse. No entanto, para garantir que o desempenho do pool de SQL seja mantido em escala, alguns recursos são limitados, se comparado ao SQL Server. Este artigo realça as diferenças e lista as outras.
Níveis de isolamento da transação
O pool de SQL dedicado implementa transações ACID. O nível de isolamento do suporte transacional usa como padrão READ UNCOMMITTED. Você pode alterá-lo para to READ COMMITTED SNAPSHOT ISOLATION selecionando ON na opção de banco de dados READ_COMMITTED_SNAPSHOT para um banco de dados do usuário quando conectado ao banco de dados mestre.
Após a habilitação, todas as transações nesse banco de dados serão executadas em READ COMMITTED SNAPSHOT ISOLATION, e a configuração READ UNCOMMITTED no nível da sessão não será respeitada. Confira Opções ALTER DATABASE SET (Transact-SQL) para detalhes.
Tamanho da transação
Uma única transação de modificação de dados é limitada em tamanho. O limite é aplicado por distribuição. Dessa forma, a alocação total pode ser calculada multiplicando o limite pela contagem de distribuição.
Para chegar a uma aproximação do número máximo de linhas na transação, divida o limite de distribuição pelo tamanho total de cada linha. Para colunas de tamanho variável, considere o uso de um tamanho médio de coluna em vez do tamanho máximo.
Na tabela abaixo, foram feitas as seguintes suposições:
- Ocorreu uma distribuição uniforme dos dados
- O tamanho médio da linha é de 250 bytes
Gen2
DWU | Limite por distribuição (GB) | Número de distribuições | Tamanho máximo de transações (GB) | Nº de linhas por distribuição | Máximo de linhas por transação |
---|---|---|---|---|---|
DW100c | 1 | 60 | 60 | 4\.000.000 | 240.000.000 |
DW200c | 1.5 | 60 | 90 | 6\.000.000 | 360.000.000 |
DW300c | 2.25 | 60 | 135 | 9\.000.000 | 540.000.000 |
DW400c | 3 | 60 | 180 | 12.000.000 | 720.000.000 |
DW500c | 3,75 | 60 | 225 | 15.000.000 | 900.000.000 |
DW1000c | 7.5 | 60 | 450 | 30.000.000 | 1\.800.000.000 |
DW1500c | 11,25 | 60 | 675 | 45.000.000 | 2\.700.000.000 |
DW2000c | 15 | 60 | 900 | 60.000.000 | 3\.600.000.000 |
DW2500c | 18,75 | 60 | 1125 | 75.000.000 | 4\.500.000.000 |
DW3000c | 22,5 | 60 | 1\.350 | 90.000.000 | 5\.400.000.000 |
DW5000c | 37,5 | 60 | 2\.250 | 150.000.000 | 9\.000.000.000 |
DW6000c | 45 | 60 | 2\.700 | 180.000.000 | 10.800.000.000 |
DW7500c | 56,25 | 60 | 3\.375 | 225.000.000 | 13.500.000.000 |
DW10000c | 75 | 60 | 4\.500 | 300.000.000 | 18.000.000.000 |
DW15000c | 112,5 | 60 | 6\.750 | 450.000.000 | 27.000.000.000 |
DW30000c | 225 | 60 | 13.500 | 900.000.000 | 54.000.000.000 |
Gen1
DWU | Limite por distribuição (GB) | Número de distribuições | Tamanho máximo de transações (GB) | Nº de linhas por distribuição | Máximo de linhas por transação |
---|---|---|---|---|---|
DW100 | 1 | 60 | 60 | 4\.000.000 | 240.000.000 |
DW200 | 1.5 | 60 | 90 | 6\.000.000 | 360.000.000 |
DW300 | 2.25 | 60 | 135 | 9\.000.000 | 540.000.000 |
DW400 | 3 | 60 | 180 | 12.000.000 | 720.000.000 |
DW500 | 3,75 | 60 | 225 | 15.000.000 | 900.000.000 |
DW600 | 4.5 | 60 | 270 | 18.000.000 | 1\.080.000.000 |
DW1000 | 7.5 | 60 | 450 | 30.000.000 | 1\.800.000.000 |
DW1200 | 9 | 60 | 540 | 36.000.000 | 2\.160.000.000 |
DW1500 | 11,25 | 60 | 675 | 45.000.000 | 2\.700.000.000 |
DW2000 | 15 | 60 | 900 | 60.000.000 | 3\.600.000.000 |
DW3000 | 22,5 | 60 | 1\.350 | 90.000.000 | 5\.400.000.000 |
DW6000 | 45 | 60 | 2\.700 | 180.000.000 | 10.800.000.000 |
O limite de tamanho de transação é aplicado por transação ou operação. Ele não é aplicado em todas as transações simultâneas. Portanto, cada transação tem permissão para gravar essa quantidade de dados no log.
Para otimizar e minimizar a quantidade de dados gravados no log, consulte o artigo Melhores práticas de transações.
Aviso
O tamanho máximo de transações só pode ser obtido para tabelas distribuídas HASH ou ROUND_ROBIN nas quais o espalhamento de dados é uniforme. Se a transação estiver gravando dados de maneira distorcida nas distribuições, provavelmente, o limite será alcançado antes do tamanho máximo de transações.
Estado da transação
O pool de SQL dedicado usa a função XACT_STATE() com valor -2 para relatar uma transação com falha. Esse valor significa que a transação falhou e está marcada para reversão somente.
Observação
O uso de -2 pela função XACT_STATE para denotar uma transação com falha representa um comportamento diferente para o SQL Server. O SQL Server usa o valor -1 para representar uma transação não confirmável. O SQL Server consegue tolerar alguns erros dentro de uma transação sem precisar ser marcado como não confirmável. Por exemplo, SELECT 1/0
causaria um erro, mas não forçaria uma transação em um estado não confirmável. O SQL Server também permite leituras na transação não confirmável. No entanto, o pool de SQL dedicado não permite que você faça isso. Se um erro ocorrer dentro de uma transação do pool de SQL dedicado, ele entrará automaticamente no estado -2, e você não conseguirá mais executar instruções do tipo select até que a instrução seja revertida. Portanto, é importante verificar o código do aplicativo para ver se ele usa XACT_STATE(), pois você poderá precisar modificar o código.
Por exemplo, no SQL Server, você verá uma transação com esta aparência:
SET NOCOUNT ON;
DECLARE @xact_state smallint = 0;
BEGIN TRAN
BEGIN TRY
DECLARE @i INT;
SET @i = CONVERT(INT,'ABC');
END TRY
BEGIN CATCH
SET @xact_state = XACT_STATE();
SELECT ERROR_NUMBER() AS ErrNumber
, ERROR_SEVERITY() AS ErrSeverity
, ERROR_STATE() AS ErrState
, ERROR_PROCEDURE() AS ErrProcedure
, ERROR_MESSAGE() AS ErrMessage
;
IF @@TRANCOUNT > 0
BEGIN
ROLLBACK TRAN;
PRINT 'ROLLBACK';
END
END CATCH;
IF @@TRANCOUNT >0
BEGIN
PRINT 'COMMIT';
COMMIT TRAN;
END
SELECT @xact_state AS TransactionState;
O código anterior oferece a seguinte mensagem de erro:
Msg 111233, Nível 16, Estado 1, Linha 1 111233; a transação atual foi anulada, e as alterações pendentes foram revertidas. Causa: uma transação em um estado de somente reversão não foi revertida explicitamente antes de uma instrução DDL, DML ou SELECT.
Você não receberá a saída das funções ERROR_*.
No pool de SQL dedicado, o código precisa ser levemente alterado:
SET NOCOUNT ON;
DECLARE @xact_state smallint = 0;
BEGIN TRAN
BEGIN TRY
DECLARE @i INT;
SET @i = CONVERT(INT,'ABC');
END TRY
BEGIN CATCH
SET @xact_state = XACT_STATE();
IF @@TRANCOUNT > 0
BEGIN
ROLLBACK TRAN;
PRINT 'ROLLBACK';
END
SELECT ERROR_NUMBER() AS ErrNumber
, ERROR_SEVERITY() AS ErrSeverity
, ERROR_STATE() AS ErrState
, ERROR_PROCEDURE() AS ErrProcedure
, ERROR_MESSAGE() AS ErrMessage
;
END CATCH;
IF @@TRANCOUNT >0
BEGIN
PRINT 'COMMIT';
COMMIT TRAN;
END
SELECT @xact_state AS TransactionState;
O comportamento esperado é observado agora. O erro na transação é gerenciado e as funções ERROR_* fornecem valores conforme o esperado.
Tudo o que mudou é que o ROLLBACK da transação deve ocorrer antes da leitura das informações de erro no bloco CATCH.
Função Error_line()
Também vale a pena observar que o pool de SQL dedicado não implementa nem aceita a função ERROR_LINE(). Se você estiver usando esta função em seu código, será necessário removê-la para que fique em conformidade com o pool de SQL dedicado. Em vez disso, use rótulos de consulta em seu código para implementar a funcionalidade equivalente. Para saber mais, confira o artigo RÓTULO.
Uso do THROW e do RAISERROR
O THROW é a implementação mais moderna para lançar exceções no pool de SQL dedicado, mas o RAISERROR também pode ser usado. No entanto, existem algumas diferenças que valem a pena prestar atenção.
- Os números das mensagens de erro definidas pelo usuário não podem estar no intervalo de 100.000 a 150.000 para o THROW
- As mensagens de erro do RAISERROR são fixadas em 50.000
- Não há suporte para o uso de sys.messages
Limitações
O pool de SQL dedicado tem algumas outras restrições relacionadas a transações. Elas são as seguintes:
- Sem transações distribuídas
- Não há transações aninhadas permitidas
- Não são permitidos pontos de salvamento
- Nenhuma transação nomeada
- Nenhuma transação marcada
- Não há suporte para DDL, como CREATE TABLE em uma transação definida pelo usuário
Próximas etapas
Para saber mais sobre a otimização das transações, consulte Transactions best practices (Melhores práticas de transações). Também existem guias adicionais de melhores práticas para Pool de SQL dedicado e Pool de SQL sem servidor.