Est-ce une mauvaise pratique de toujours créer une transaction?


88

Est-ce une mauvaise pratique de toujours créer une transaction?

Par exemple, il est recommandé de créer une transaction pour rien d’autre SELECT?

Quel est le coût de la création d’une transaction quand ce n’est pas vraiment nécessaire?

Même si vous utilisez un niveau d'isolement comme READ UNCOMMITTED, est-ce une mauvaise pratique?


1
En regardant l'impact de BEGIN TRAN SELECT ... COMMITvs vs, SELECTil semble y avoir une différence de performance extrêmement mineure .
Martin Smith

Réponses:


100

Une mauvaise pratique est-elle toujours de créer une transaction?

Cela dépend de quel contexte vous parlez ici. S'il s'agit d'une mise à jour, il est fortement recommandé d'utiliser explicitement TRANSACTIONS. Si c'est un SELECT, alors NO (explicitement).

Mais attendez il y a plus à comprendre d'abord: Tout dans le serveur SQL est contenu dans une transaction.

Lorsque l'option de session IMPLICIT_TRANSACTIONSest OFFet que vous spécifiez explicitement begin tran, commit/rollbackil s'agit généralement d'une transaction explicite . Sinon, vous obtenez une transaction autocommit.

Quand IMPLICIT_TRANSACTIONSest ONune transaction implicite est démarré automatiquement lors de l' exécution d' un des types de déclarations documentées dans les livres article en ligne (par exemple SELECT/ UPDATE/ CREATE) et il doit être validée ou annulée explicitement. L'exécution de BEGIN TRANdans ce mode incrémenterait @@TRANCOUNTet lancerait une autre transaction "imbriquée".

Pour changer de mode, vous utiliseriez

SET IMPLICIT_TRANSACTIONS ON

ou

SET IMPLICIT_TRANSACTIONS OFF

select @@OPTIONS & 2

si ci-dessus renvoie 2, vous êtes en mode de transaction implicite. Si la valeur renvoyée est 0, vous vous engagez automatiquement.

combien coûte la création d'une transaction quand ce n'est pas vraiment nécessaire?

Des transactions sont nécessaires pour passer de la base de données d’un état cohérent à un autre état cohérent. Les transactions n'ont pas de coût car il n'y a pas d'alternative aux transactions. Voir: Utilisation des niveaux d'isolement basés sur le versioning de ligne

Même si vous utilisez un niveau d'isolation, read_uncomitted. Est-ce une mauvaise pratique? car il ne devrait pas avoir de problèmes de verrouillage.

Le niveau d'isolation READ_UNCOMMITED autorisera les lectures modifiées par définition, c'est-à-dire qu'une transaction sera en mesure de voir les modifications non validées apportées par une autre transaction. Ce niveau d’isolement atténue l’essentiel du verrouillage - méthode d’acquisition de verrous pour protéger l’accès simultané à la base de données.

Vous pouvez l'utiliser au niveau de la connexion / de la requête, de sorte que cela n'affecte pas les autres requêtes.

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

J'ai trouvé un article intéressant de Jeff Atwood décrivant les blocages imputables à Dining Philosophers Puzzle et décrivant le niveau d'isolement de l' instantané pris en lecture .

MODIFIER:

Par curiosité, j’ai fait quelques tests pour mesurer l’impact sur T-log avec des compteurs Perfmon tels que Log Bytes Flushed / Sec, Log Flush Waits / Sec (le nombre de validations par seconde qui attend que le vidage du journal se produise se présente), comme indiqué dans le graphique ci-dessous:

entrez la description de l'image ici

exemple de code:

create table testTran (id int, Name varchar(8))
go

-- 19 sec
-- Autocommit transaction
declare @i int
set @i = 0
while @i < 100000
begin 
insert into testTran values (1,'Kin Shah')
set @i = @i+1
end
---------------------------------------------------
-- 2 sec
-- Implicit transaction
SET IMPLICIT_TRANSACTIONS ON
declare @i int
set @i = 0
while @i < 100000
begin 
insert into testTran values (1,'Kin Shah')
set @i = @i+1
end
COMMIT;
SET IMPLICIT_TRANSACTIONS OFF


----------------------------------------------------
-- 2 sec
-- Explicit transaction
declare @i int
set @i = 0
BEGIN TRAN
WHILE @i < 100000
Begin
INSERT INTO testTran values (1,'Kin Shah')
set @i = @i+1
End
COMMIT TRAN

Transactions à signature automatique : (édité comme souligné par @TravisGan)

  • L'insertion a pris 19 secondes.
  • Chaque AutoCommit videra la mémoire tampon du journal T sur le disque pour autocomit (après que @TravisGan soit surligné et que je l’aie manquée).
  • Le processus CHECKPOINT s'achèvera rapidement car la quantité de mémoire tampon de journal sale à vider sera réduite car il fonctionnera souvent en mode silencieux.

Transaction IMPLICITE & Explicite:

  • L'insertion a pris 2 secondes.
  • Pour la transaction EXPLICIT, les tampons de journal ne seront vidés que lorsqu'ils sont pleins.
  • Contrairement à la transaction Autocommit, dans la transaction EXPLICIT, le processus CHECKPOINT durera plus longtemps car il aura plus de tampons de journal à vider (rappelez-vous que les tampons de journal ne sont vidés que lorsqu'ils sont pleins).

Il existe un fichier DMV sys.dm_tran_database_transactions qui renverra des informations sur les transactions au niveau de la base de données.

De toute évidence, il s’agit plutôt d’un test simpliste pour montrer l’impact. D'autres facteurs tels que le sous-système de disque, les paramètres de croissance automatique de la base de données, la taille initiale de la base de données, d'autres processus s'exécutant sur le même serveur \ base de données, etc. auront également une influence.

D'après les tests ci-dessus, il n'y a pratiquement aucune différence entre les transactions implicites et explicites.

Merci à @TravisGan pour avoir aidé à ajouter plus à la réponse.


35

Une instruction SQL s'exécute toujours dans une transaction. Si vous n'en démarrez pas une explicitement, chaque instruction SQL s'exécutera dans une transaction d'elle-même.

Le seul choix est de regrouper plusieurs déclarations en une seule transaction. Les transactions qui couvrent plusieurs déclarations laissent des verrous qui font mal à la concurrence. Donc, "toujours" créer une transaction n'est pas une bonne idée. Vous devez équilibrer le coût par rapport à l'avantage.


1

La question est de savoir si un groupe d'opérations doit être traité comme une seule action. En d'autres termes, toutes les opérations doivent être terminées et validées avec succès, sinon aucune opération ne peut être validée. Si vous avez un scénario dans lequel vous devez lire des données préliminaires, puis effectuer des mises à jour à partir de ces données, la lecture initiale doit probablement faire partie de la transaction. Remarque: j'évite de sélectionner / insérer / mettre à jour à dessein. L'étendue de la transaction peut en réalité se situer au niveau de l'application et impliquer plusieurs opérations de base de données. Pensez à des modèles classiques tels que réservation de siège d'avion ou demande / retrait de solde bancaire. Il faut envisager le problème sous un angle plus large afin de s’assurer que l’ensemble de l’application génère des données fiables et cohérentes.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.