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?
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.
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:
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)
IMPLICITE & Transaction explicite:
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.
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.
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.