Remarque
L’accès à cette page requiert une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page requiert une autorisation. Vous pouvez essayer de modifier des répertoires.
Conseils pour l’implémentation de transactions avec un pool SQL dédié dans Azure Synapse Analytics pour le développement de solutions.
À quoi s’attendre
Comme prévu, le pool SQL dédié prend en charge les transactions dans le cadre de la charge de travail de l’entrepôt de données. Toutefois, pour garantir que les performances du pool SQL dédié sont conservées à grande échelle, certaines fonctionnalités sont limitées par rapport à SQL Server. Cet article met en évidence les différences et répertorie les autres.
Niveaux d’isolation des transactions
Le pool SQL dédié implémente des transactions ACID. Le niveau d’isolation de la prise en charge transactionnelle est défini par défaut sur READ UNCOMMITTED. Vous pouvez le modifier en READ COMMITTED SNAPSHOT ISOLATION en activant l’option de base de données READ_COMMITTED_SNAPSHOT pour une base de données utilisateur lorsqu’elle est connectée à la base de données principale.
Une fois activées, toutes les transactions de cette base de données sont exécutées sous READ COMMITTED SNAPSHOT ISOLATION et le paramètre READ UNCOMMITTED au niveau de la session ne sera pas respecté. Pour plus d’informations, consultez les options ALTER DATABASE SET (Transact-SQL).
Taille de la transaction
Une transaction de modification de données unique est limitée en taille. La limite est appliquée par distribution. Par conséquent, l’allocation totale peut être calculée en multipliant la limite par le nombre de distributions.
Pour estimer le nombre maximal de lignes dans la transaction, divisez la limite de distribution par la taille totale de chaque ligne. Pour les colonnes de longueur variable, envisagez de prendre une longueur moyenne de colonne plutôt que d’utiliser la taille maximale.
Dans le tableau ci-dessous, les hypothèses suivantes ont été faites :
- Une distribution égale des données s’est produite
- La longueur moyenne de ligne est de 250 octets
Deuxième génération
| DWU | Plafond par distribution (Go) | Nombre de distributions | Taille maximale des transactions (Go) | Nombre de lignes par distribution | Nombre maximal de lignes par transaction |
|---|---|---|---|---|---|
| DW100c | 1 | soixante | soixante | 4,000,000 | 240,000,000 |
| DW200c | 1.5 | soixante | 90 | 6,000,000 | 360 000 000 |
| DW300c | 2,25 | soixante | 135 | 9,000,000 | 540,000,000 |
| DW400c | 3 | soixante | 180 | 12,000,000 | 720,000,000 |
| DW500c | 3,75 | soixante | 225 | 15 000 000 | 900,000,000 |
| DW1000c | 7,5 | soixante | 450 | 30,000,000 | 1,800,000,000 |
| DW1500c | 11.25 | soixante | 675 | 45,000,000 | 2,700,000,000 |
| DW2000c | 15 | soixante | 900 | 60 000 000 | 3,600,000,000 |
| DW2500c | 18.75 | soixante | 1125 | 75,000,000 | 4,500,000,000 |
| DW3000c | 22,5 | soixante | 1,350 | 90 000 000 | 5,400,000,000 |
| DW5000c | 37,5 | soixante | 2,250 | 150,000,000 | 9,000,000,000 |
| DW6000c | 45 | soixante | 2,700 | 180,000,000 | 10,800,000,000 |
| DW7500c | 56.25 | soixante | 3,375 | 225,000,000 | 13,500,000,000 |
| DW10000c | 75 | soixante | 4 500 | 300,000,000 | 18,000,000,000 |
| DW15000c | 112.5 | soixante | 6,750 | 450,000,000 | 27,000,000,000 |
| DW30000c | 225 | soixante | 13,500 | 900,000,000 | 54,000,000,000 |
Gen1
| DWU | Plafond par distribution (Go) | Nombre de distributions | Taille maximale des transactions (Go) | Nombre de lignes par distribution | Nombre maximal de lignes par transaction |
|---|---|---|---|---|---|
| DW100 | 1 | soixante | soixante | 4,000,000 | 240,000,000 |
| DW200 | 1.5 | soixante | 90 | 6,000,000 | 360 000 000 |
| DW300 | 2,25 | soixante | 135 | 9,000,000 | 540,000,000 |
| DW400 | 3 | soixante | 180 | 12,000,000 | 720,000,000 |
| DW500 | 3,75 | soixante | 225 | 15 000 000 | 900,000,000 |
| DW600 | 4,5 | soixante | 270 | 18 000 000 | 1,080,000,000 |
| DW1000 | 7,5 | soixante | 450 | 30,000,000 | 1,800,000,000 |
| DW1200 | 9 | soixante | 540 | 36 000 000 | 2,160,000,000 |
| DW1500 | 11.25 | soixante | 675 | 45,000,000 | 2,700,000,000 |
| DW2000 | 15 | soixante | 900 | 60 000 000 | 3,600,000,000 |
| DW3000 | 22,5 | soixante | 1,350 | 90 000 000 | 5,400,000,000 |
| DW6000 | 45 | soixante | 2,700 | 180,000,000 | 10,800,000,000 |
La limite de taille de transaction est appliquée par transaction ou opération. Elle n’est pas appliquée à toutes les transactions simultanées. Par conséquent, chaque transaction est autorisée à écrire cette quantité de données dans le journal.
Pour optimiser et réduire la quantité de données écrites dans le journal, reportez-vous à l’article sur les meilleures pratiques des transactions .
Avertissement
La taille maximale des transactions ne peut être obtenue que pour hash ou ROUND_ROBIN tables distribuées où la propagation des données est même. Si la transaction écrit des données de manière biaisée dans les distributions, la limite risque d'être atteinte avant la taille maximale de la transaction.
État de la transaction
Le pool SQL dédié utilise la fonction XACT_STATE() pour signaler une transaction ayant échoué à l’aide de la valeur -2. Cette valeur signifie que la transaction a échoué et est marquée uniquement pour un retrait.
Note
L’utilisation de -2 par la fonction XACT_STATE pour indiquer qu’une transaction ayant échoué représente un comportement différent de SQL Server. SQL Server utilise la valeur -1 pour représenter une transaction noncommittable. SQL Server peut tolérer certaines erreurs à l’intérieur d’une transaction sans que celle-ci ait à être marquée comme impossible à valider. Par exemple, SELECT 1/0 provoquerait une erreur sans forcer une transaction dans un état non-engageable. SQL Server autorise également les lectures dans les transactions non validées. Toutefois, le pool SQL dédié ne vous permet pas de le faire. Si une erreur se produit à l’intérieur d’une transaction de pool SQL dédiée, elle entre automatiquement dans l’état -2 et vous ne pourrez pas effectuer d’instructions select supplémentaires tant que l’instruction n’a pas été restaurée. Il est donc important de vérifier que votre code d’application doit voir s’il utilise XACT_STATE() car vous devrez peut-être apporter des modifications de code.
Par exemple, dans SQL Server, vous pouvez voir une transaction qui ressemble à ce qui suit :
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;
Le code précédent fournit le message d’erreur suivant :
Msg 111233, Level 16, State 1, Line 1 111233 ; La transaction actuelle a été abandonnée et toutes les modifications en attente ont été annulées. Cause : une transaction dans un état de retour arrière uniquement n'a pas été annulée explicitement avant une instruction DDL, DML ou SELECT.
Vous n’obtiendrez pas la sortie des fonctions ERROR_*.
Dans le pool SQL dédié, le code doit être légèrement modifié :
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;
Le comportement attendu est maintenant observé. L’erreur dans la transaction est gérée et les fonctions ERROR_* fournissent des valeurs comme prévu.
Tout ce qui a changé est que le ROLLBACK de la transaction devait se produire avant la lecture des informations d’erreur dans le bloc CATCH.
fonction Error_Line()
Il est également important de noter que le pool SQL dédié n’implémente pas ou ne prend pas en charge la fonction ERROR_LINE(). Si vous disposez de cette fonction dans votre code, vous devez la supprimer pour qu’elle soit conforme au pool SQL dédié. Utilisez plutôt des étiquettes de requête dans votre code pour implémenter des fonctionnalités équivalentes. Pour plus d’informations, consultez l’article LABEL .
Utilisation de THROW et RAISERROR
THROW est l’implémentation plus moderne pour déclencher des exceptions dans un pool SQL dédié, mais RAISERROR est également pris en charge. Toutefois, il existe quelques différences qui méritent d’être attentifs.
- Les numéros de messages d’erreur définis par l’utilisateur ne peuvent pas se trouver dans la plage 100 000 - 150 000 pour THROW
- Les messages d’erreur RAISERROR sont fixés à 50 000
- L’utilisation de sys.messages n’est pas prise en charge
Limites
Le pool SQL dédié a quelques autres restrictions liées aux transactions. Elles sont les suivantes :
- Aucune transaction distribuée
- Aucune transaction imbriquée n’est autorisée
- Aucun point de sauvegarde autorisé
- Aucune transaction nommée
- Aucune transaction marquée
- Aucune prise en charge de DDL comme CREATE TABLE dans une transaction définie par l’utilisateur
Étapes suivantes
Pour en savoir plus sur l’optimisation des transactions, consultez les meilleures pratiques relatives aux transactions. Des guides de bonnes pratiques supplémentaires sont également fournis pour le pool SQL dédié et le pool SQL serverless.