web-dev-qa-db-fra.com

Quels événements se produisent toujours dans une transaction qui est annulée?

Est-il vrai que toutes les modifications de données sont annulées lorsque la transaction dont elles font partie est annulée?

Par exemple, si un curseur qui vient d'exécuter 100 fois une procédure stockée met à jour une table à chaque itération, toutes ces mises à jour sont-elles annulées?

Une instruction DDL serait-elle annulée? ... comme DROP TABLE ou CREATE VIEW? Et DROP DATABASE?

Je sais que certaines instructions sont toujours exécutées, comme PRINT "MESSAGE".

J'essaie juste de me faire une idée des types d'événements qui se produisent encore.

7
J.D.

Pour les instructions autorisées à s'exécuter dans une transaction explicite (c'est-à-dire BEGIN TRAN, ou le ciel ne plaise IMPLICIT_TRANSACTIONS est ON), je ne connais que les deux suivants qui ne seront pas affectés par un ROLLBACK (bien que techniquement les deux soient quelque peu "tricheurs" dans un sens):

  1. Instructions DML par rapport aux variables de table (variables, même variables de table, ne participent pas aux transactions)
  2. instructions exécutées via un serveur lié et OPENQUERY (même si vous utilisez une définition de serveur de bouclage pour vous connecter à l'instance actuelle) si vous avez la propriété de serveur lié "promotion de transaction proc à distance" désactivé (afin qu'il ne tente pas de s'inscrire dans la transaction en cours).

    OPENQUERY (avec cette option désactivée) fonctionne car il établit une connexion distincte. Il existe d'autres méthodes similaires pour établir une connexion distincte dans T-SQL. David Browne, dans un commentaire, a mentionné les procédures stockées étendues. Nous pouvons également ajouter des méthodes SQLCLR (quel que soit le type d'objet T-SQL auquel elles sont exposées) à cette liste, mais uniquement si vous établissez une connexion régulière/externe, et en précisant "enlist=false; "dans la chaîne de connexion. Nous pouvons probablement également ajouter les procédures stockées OLE Automation (c.-à-d. sp_OA*), mais je n'en suis pas sûr à 100%.

  3. Il peut y avoir une ou deux instructions qui peuvent être exécutées dans une transaction explicite mais ne peuvent pas être annulées, et je pense j'ai peut-être rencontré cela il y a de nombreuses années, mais je ne me souviens pas ce que c'est et aurait pu être erreur utilisateur (un autre utilisateur, bien sûr ;-), vous devrez donc consulter la documentation pour connaître les détails de chaque instruction/opération et/ou tester autant que vous le pouvez (parfois la documentation est incorrecte ... cela arrive).
  4. Je ne sais pas si cela compte ou non car ce n'est pas un changement explicite, mais ce n'est pas quelque chose qui revient à ce qu'il était avant le début de la transaction (car cela n'a même pas de sens qu'il le puisse): Tibor Karaszi a noté dans un commenter que "consommer une valeur d'identité/séquence" pourrait être qualifié. J'ai testé et confirmé que les séquences ne renvoient pas les valeurs demandées.

    De même, une autre valeur qui est l'état de la base de données, et non spécifiquement les données utilisateur, qui n'est pas affectée par une restauration est la valeur d'horodatage actuelle/dernière utilisée (c'est par base de données et est retournée par la variable système @@DBTS ; également confirmé par test)

  5. Je ne sais pas si ceux-ci comptent ou non car ils ne sont ni un changement explicite ni même l'état de la base de données, mais leurs valeurs ne sont pas affectées par une restauration: dans un commentaire, David Browne a mentionné SESSION_CONTEXT , qui est une propriété de chaque session. Dans le même ordre d'idées, nous pouvons inclure les éléments connexes/similaires CONTEXT_INFO

si un curseur qui venait d'exécuter une procédure stockée 100 fois qui mettait à jour une table à chaque itération, toutes ces mises à jour seraient-elles annulées?

Oui, c'est le but des transactions explicites: regrouper les déclarations en une unité de travail atomique.

Une instruction DDL serait-elle annulée? ... comme DROP TABLE ou CREATE VIEW? Et DROP DATABASE?

Certains (peut-être la plupart) oui. Certains non. Vous devriez probablement tester. Par exemple, voici quelques DDL qui annulent:

USE [tempdb];

IF (OBJECT_ID(N'dbo.DropMe') IS NOT NULL)
BEGIN
  DROP TABLE dbo.DropMe;
END;

CREATE TABLE dbo.DropMe (col1 INT);

BEGIN TRAN;

DROP TABLE dbo.DropMe;

ROLLBACK TRAN;

SELECT * FROM dbo.[DropMe];

Mais, inversement, voici une DDL qui ne peut pas être exécutée dans une transaction explicite (ou implicite):

CREATE DATABASE [DropMe];
BEGIN TRAN;
DROP DATABASE [DropMe];
/*
Msg 574, Level 16, State 0, Line XXXXX
DROP DATABASE statement cannot be used inside a user transaction.
*/
ROLLBACK;

Alors, prenez simplement les deux exemples ci-dessus et retravaillez-les pour d'autres déclarations qui vous intéressent ou dont vous avez besoin d'une réponse définitive.

8
Solomon Rutzky

est-il vrai que toutes les modifications de données sont annulées lorsque la transaction dont elles font partie est annulée?

Oui. C'est le sens entier d'une transaction.

Par exemple, si un curseur qui vient d'exécuter une procédure stockée 100 fois a mis à jour une table à chaque itération, toutes ces mises à jour seraient-elles annulées?

Telle est la définition de tous les changements.

Une déclaration DDL serait-elle annulée?.

Dépend de la déclaration. RTFM est le seul moyen d'obtenir ce tri (c'est-à-dire qu'il est documenté par commande) mais généralement DDL et DML en une seule transaction ne se mélangent pas et en général vous feriez mieux de supposer que tandis que DML les modifications SONT transactionnelles (l'ajout d'un champ est une transaction et soit toutes les lignes l'obtiennent, soit aucune) vous êtes beaucoup mieux en supposant que la prise en charge des transactions est limitée. Cela dit, cela dépend aussi énormément de la version du serveur sql. Et les frappeurs très lourds comme drop database - ils suppriment réellement les fichiers physiques, vous savez. Ils n'exécutent pas non plus "dans la base de données" - la base de données de dépôt SERAIT une transaction sur la base de données principale et sur l'ensemble du système.

Nous exécutons généralement DML dans les transactions ces jours-ci, et cela fonctionne - mais nous avons un moyen dans nos scripts de changement (avec un commentaire sur la première ligne) de désactiver le wrapping des transactions car CERTAINES modifications dans DML ne s'exécutent pas dans les transactions.

Je sais que certaines instructions sont toujours exécutées, comme PRINT "MESSAGE".

TOUTES les instructions s'exécutent. La restauration n'est pas en cours d'exécution. c'est juste que PRINT ne peut pas être annulé car ce n'est pas un changement de données;)

2
TomTom

Je viens de lancer quelques tests, voici les résultats:

  1. La suppression de la base de données ne peut pas être effectuée dans une transaction explicite (commencer le transfert ...)
    SQL Server lance:

    L'instruction DROP DATABASE ne peut pas être utilisée dans une transaction utilisateur.

  2. Drop table vous pouvez le faire dans une transaction explicite sans aucun problème

  3. Créer une vue - vous pouvez le faire, mais vous devez d'abord exécuter begin tran ..., puis exécuter create view ..., puis annuler ou valider. Vous pouvez donc le faire étape par étape, mais pas en une seule fois car SQL Server lancera:

    'CREATE VIEW' doit être la première instruction d'un lot de requêtes.

Donc, si le curseur exécute SP et met simplement à jour les données dans une table et se trouve dans une transaction explicite, il peut être annulé. Mais si votre curseur/SP supprime également certaines bases de données alors non, il peut ne pas être annulé

1
Aleksey Vitsko