web-dev-qa-db-fra.com

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

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 qu'un simple SELECT?

Quel est le coût de création d'une transaction lorsqu'elle n'est pas vraiment nécessaire?

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

96
elranu

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

Cela dépend du contexte dont vous parlez ici. S'il s'agit d'une mise à jour, je recommanderais fortement d'utiliser explicitement TRANSACTIONS. Si c'est un SELECT alors NON (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_TRANSACTIONS est OFF et vous spécifiez explicitement begin tran et commit/rollback alors c'est communément appelé Explicit Transaction . Sinon, vous obtenez une transaction de validation automatique.

Quand IMPLICIT_TRANSACTIONS est ON an transaction implicite est automatiquement démarré lors de l'exécution de l'un des types d'instructions documentés dans l'article en ligne de l'ouvrage (par exemple SELECT/UPDATE/CREATE) et il doit être validé ou annulé explicitement. Exécution d'un BEGIN TRAN dans ce mode incrémenterait @@TRANCOUNT et démarrer une autre transaction "imbriquée")

Pour changer le mode dans lequel vous vous trouvez, 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. S'il renvoie 0, vous êtes en autocommit.

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

Des transactions sont nécessaires pour faire passer la base de données d'un état cohérent à un autre état cohérent. Les transactions n'ont aucun coût car il n'y a pas d'alternative aux transactions. Reportez-vous: tilisation des niveaux d'isolement basés sur le contrôle de version des lignes

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

Le niveau d'isolement READ_UNCOMMITED permettra des lectures sales par définition, c'est-à-dire qu'une transaction pourra voir les modifications non validées apportées par une autre transaction. Ce que ce niveau d'isolement fait, il détend la surcharge de verrouillage - méthode d'acquisition de verrous pour protéger la simultanéité de la base de données.

Vous pouvez l'utiliser sur un niveau de connexion/requête, afin qu'il n'affecte pas les autres requêtes.

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

J'ai trouvé un article de Jeff Atwood décrivant les blocages dus au casse-tête des philosophes de la salle à manger et décrivant lire l'instantané engagé le niveau d'isolement.

MODIFIER:

Par curiosité, j'ai fait un test pour mesurer l'impact sur le T-log avec des compteurs Perfmon comme Log Bytes Flowed/Sec, Log Flush Waits/Sec (nombre de validations par seconde qui attendent que le vidage de LOG se produise) comme ci-dessous:

enter image description here

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 de validation automatique : (Modifié comme mis en évidence par @TravisGan)

  • L'insertion a pris 19 secondes.
  • Chaque Autocommit videra le tampon T-log sur le disque en raison de l'autocomit (après que @TravisGan a été mis en surbrillance, et j'ai manqué cela pour le mentionner).
  • Le processus CHECKPOINT se terminera rapidement, car la quantité de mémoire tampon de journal sale devant être vidée sera moindre car il s'exécute souvent de manière silencieuse.

IMPLICITE & Transaction 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 prendra plus de temps car il aura plus de tampons de journal à vider (rappelez-vous que les tampons de journal sont vidés uniquement lorsqu'ils sont pleins).

Il existe un 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 plus d'une sorte de test simpliste pour montrer l'impact. D'autres facteurs comme 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 d'avoir aidé à ajouter plus à la réponse.

109
Kin Shah

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

Le seul choix est de regrouper plusieurs relevés en une seule transaction. Les transactions qui s'étendent sur plusieurs relevés laissent des verrous qui nuisent à la concurrence. Donc, "toujours" créer une transaction n'est pas une bonne idée. Vous devez équilibrer le coût et l'avantage.

36
Andomar

La question est de savoir si un groupe d'opérations doit être traité comme une action unique. En d'autres termes, toutes les opérations doivent être terminées et validées avec succès ou aucune des opérations ne peut être validée. Si vous avez un scénario qui vous oblige à lire les données préliminaires puis à effectuer des mises à jour en fonction de ces données, la lecture initiale devrait probablement faire partie de la transaction. Remarque: j'évite de sélectionner/insérer/mettre à jour exprès. La portée de la transaction peut en fait être au niveau de l'application et impliquer plusieurs opérations de base de données. Pensez à des modèles classiques tels que la réservation de siège d'avion ou la requête/retrait de solde bancaire. Il faut avoir une vision plus large du problème pour garantir que l'application entière génère des données fiables et cohérentes.

1
Ray