Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Fonctionnement des transactions implicites dans SQL Server

Il existe quatre modes de transaction dans SQL Server. L'un d'eux est le mode implicite.

Dans SQL Server, une transaction implicite est lorsqu'une nouvelle transaction est lancée implicitement lorsque la transaction précédente se termine, mais chaque transaction est explicitement terminée avec un COMMIT ou ROLLBACK déclaration.

Cela ne doit pas être confondu avec le mode autocommit, où la transaction est démarrée et terminée implicitement.

Les quatre modes de transaction

SQL Server peut fonctionner dans les modes de transaction suivants :

Mode de transaction Description
Transaction de validation automatique Chaque relevé individuel est une transaction.
Transaction implicite Une nouvelle transaction est lancée implicitement lorsque la transaction précédente se termine, mais chaque transaction est explicitement terminée, généralement avec un COMMIT ou ROLLBACK déclaration en fonction du SGBD.
Transaction explicite Commence explicitement par une ligne telle que START TRANSACTION , BEGIN TRANSACTION ou similaire, selon le SGBD, et explicitement validé ou annulé avec les instructions pertinentes.
Transaction groupée Applicable uniquement à plusieurs ensembles de résultats actifs (MARS). Une transaction explicite ou implicite qui démarre sous une session MARS devient une transaction de portée par lots.

Mode implicite vs validation automatique

Dans SQL Server, certaines instructions démarrent automatiquement une transaction lors de leur exécution. C'est comme s'ils étaient précédés d'un BEGIN TRANSACTION invisible déclaration.

Dans la plupart des cas, ces transactions sont également validées implicitement, comme s'il y avait un COMMIT TRANSACTION invisible déclaration. Ces transactions sont dites en mode autocommit .

Dans d'autres cas, il n'y a pas de COMMIT TRANSACTION invisible pour correspondre à l'invisible BEGIN TRANSACTION déclaration. La transaction reste en cours jusqu'à ce que vous la validiez explicitement ou l'annuliez avec un COMMIT TRANSACTION ou ROLLBACK TRANSACTION déclaration. Dans ce cas, la transaction est dite en mode implicite .

Que la transaction s'exécute en mode implicite ou en mode autocommit dépend de votre IMPLICIT_TRANSACTIONS réglage.

Déclarations qui démarrent une transaction implicite

Les instructions suivantes démarrent une transaction implicite dans SQL Server.

  • ALTER TABLE
  • BEGIN TRANSACTION
  • CREATE
  • DELETE
  • DROP
  • FETCH
  • GRANT
  • INSERT
  • OPEN
  • REVOKE
  • SELECT (sauf ceux qui ne sélectionnent pas dans une table, comme SELECT GETDATE() ou SELECT 1*1 )
  • TRUNCATE TABLE
  • UPDATE

Chaque fois que vous exécutez ces instructions T-SQL, vous démarrez une transaction. La plupart du temps, la transaction sera automatiquement validée. Vous avez donc commencé et terminé la transaction sans avoir à le faire explicitement.

Cependant, selon votre IMPLICIT_TRANSACTIONS paramètre, vous devrez peut-être valider la transaction explicitement.

Quand IMPLICIT_TRANSACTIONS est OFF

Lorsque votre IMPLICIT_TRANSACTIONS le paramètre est OFF , les instructions ci-dessus effectuent des transactions en mode autocommit. Autrement dit, ils commencent et mettre fin implicitement à la transaction.

C'est comme avoir un BEGIN TRANSACTION invisible et un COMMIT TRANSACTION invisible déclaration, le tout à partir d'une seule déclaration.

Dans ce cas, vous n'avez rien à faire pour valider ou annuler la transaction. C'était déjà fait pour vous.

Quand IMPLICIT_TRANSACTIONS est ON

Lorsque votre IMPLICIT_TRANSACTIONS le réglage est ON , les instructions ci-dessus se comportent légèrement différemment.

Lorsque IMPLICIT_TRANSACTIONS le réglage est ON , les instructions ci-dessus obtiennent un BEGIN TRANSACTION invisible mais ils ne reçoivent pas de COMMIT TRANSACTION correspondant déclaration.

Cela signifie que vous devez explicitement valider ou annuler la transaction vous-même.

Cependant, lorsque le mode de transaction est implicite, aucun BEGIN TRANSACTION invisible est émis si une transaction est déjà en cours.

Exemple

Voici un exemple pour illustrer le concept.

SELECT @@TRANCOUNT AS TransactionCount;
SET IMPLICIT_TRANSACTIONS OFF;
SELECT TOP 1 ProductName, ProductPrice FROM Products;
SELECT @@TRANCOUNT AS TransactionCount;

Résultat :

+--------------------+
| TransactionCount   |
|--------------------|
| 0                  |
+--------------------+
(1 row affected)
Commands completed successfully.
+-------------------------+----------------+
| ProductName             | ProductPrice   |
|-------------------------+----------------|
| Left handed screwdriver | 25.99          |
+-------------------------+----------------+
(1 row affected)
+--------------------+
| TransactionCount   |
|--------------------|
| 0                  |
+--------------------+
(1 row affected)

Dans ce cas, j'ai défini IMPLICIT_TRANSACTIONS sur OFF et exécutez le SELECT déclaration. Cela signifiait que le SELECT L'instruction a été exécutée en mode autocommit et, par conséquent, la transaction a été démarrée et terminée implicitement.

@@TRANCOUNT renvoyé 0 , ce qui signifie qu'aucune transaction n'était en cours à ce stade.

Le voici à nouveau, sauf que cette fois nous avons défini IMPLICIT_TRANSACTIONS sur ON .

SELECT @@TRANCOUNT AS TransactionCount;
SET IMPLICIT_TRANSACTIONS ON;
SELECT TOP 1 ProductName, ProductPrice FROM Products;
SELECT @@TRANCOUNT AS TransactionCount;

Résultat :

+--------------------+
| TransactionCount   |
|--------------------|
| 0                  |
+--------------------+
(1 row affected)
Commands completed successfully.
+-------------------------+----------------+
| ProductName             | ProductPrice   |
|-------------------------+----------------|
| Left handed screwdriver | 25.99          |
+-------------------------+----------------+
(1 row affected)
+--------------------+
| TransactionCount   |
|--------------------|
| 1                  |
+--------------------+
(1 row affected)

Le dernier @@TRANCOUNT renvoie une valeur de 1 . Cela signifie que notre transaction est toujours en cours.

@@TRANCOUNT renvoie le nombre de BEGIN TRANSACTION déclarations qui se sont produites sur la connexion en cours. Nous n'en avons pas explicitement émis un, mais un a été implicitement émis.

Nous devons donc en fait valider cette transaction (ou l'annuler) afin de décrémenter le @@TRANCOUNT jusqu'à 0 .

COMMIT TRANSACTION;
SELECT @@TRANCOUNT AS TransactionCount;

Résultat :

+--------------------+
| TransactionCount   |
|--------------------|
| 0                  |
+--------------------+
(1 row affected)

Ainsi, le code de notre transaction implicite aurait dû inclure le COMMIT déclaration :

SELECT @@TRANCOUNT AS TransactionCount;
SET IMPLICIT_TRANSACTIONS ON;
SELECT TOP 1 ProductName, ProductPrice FROM Products;
COMMIT TRANSACTION;
SELECT @@TRANCOUNT AS TransactionCount;

Résultat :

+--------------------+
| TransactionCount   |
|--------------------|
| 0                  |
+--------------------+
(1 row affected)
Commands completed successfully.
+-------------------------+----------------+
| ProductName             | ProductPrice   |
|-------------------------+----------------|
| Left handed screwdriver | 25.99          |
+-------------------------+----------------+
(1 row affected)
Commands completed successfully.
+--------------------+
| TransactionCount   |
|--------------------|
| 0                  |
+--------------------+
(1 row affected)

ANSI_DEFAULTS

Si vous constatez que les transactions implicites sont activées de manière inattendue, cela peut être dû au ANSI_DEFAULTS paramètre.