81 votes

Que fait une transaction autour d'une seule déclaration ?

Je comprends comment une transaction peut être utile pour coordonner une paire de mises à jour. Ce que je ne comprends pas, c'est l'enveloppement de déclarations uniques dans des transactions, ce qui représente 90 % de ce que j'ai vu. En fait, dans le code de la vie réelle, il est plus courant, d'après mon expérience, de trouver une série de transactions logiquement liées, chacune enveloppée dans sa propre transaction, mais l'ensemble n'est pas enveloppé dans une transaction.

En MS-SQL, y a-t-il un avantage à intégrer des sélections, des mises à jour, des insertions ou des suppressions uniques dans une transaction ?

Je pense que c'est une programmation superstitieuse.

83voto

Charles Bretana Points 59899

Il ne fait rien. Toutes les requêtes SQL individuelles (à de rares exceptions près, comme les insertions en masse sans journal ou la suppression d'une table) sont automatiquement "dans une transaction", que vous le disiez explicitement ou non (même si elles insèrent, mettent à jour ou suppriment des millions de lignes).

EDIT : basé sur le commentaire de @Phillip ci-dessous... Dans les versions actuelles de SQL Server, même les Bulk Inserts et Truncate Table permettent d'écrire un peu de dans le journal des transactions, mais pas autant que les autres opérations. La distinction essentielle, du point de vue transactionnel, est que dans ces autres types d'opérations, les données des tables de votre base de données qui sont modifiées ne sont pas dans le journal dans un état qui permet de les annuler.

Cela signifie que les modifications apportées par l'instruction aux données de la base de données sont enregistrées dans le journal des transactions afin de pouvoir être annulées en cas d'échec de l'opération.

La seule fonction des commandes "Begin Transaction", "Commit Transaction" et "RollBack Transaction" est de vous permettre de placer deux ou plusieurs instructions SQL individuelles dans la même transaction.

EDIT : (pour renforcer le commentaire des marques...) OUI, cela pourrait être attribué à une programmation "superstitieuse", ou cela pourrait être une indication d'une incompréhension fondamentale de la nature des transactions de base de données. Une interprétation plus charitable est que c'est simplement le résultat d'une application excessive de la cohérence qui est inappropriée et encore un autre exemple de l'euphémisme d'Emerson que :

Une cohérence stupide est le hanneton des petits esprits,
adoré par les petits hommes d'État, les philosophes et les divinités.

4 votes

Vous devriez affirmer, oui, c'est une programmation superstitieuse. =)

0 votes

@Charles, Qu'en est-il de MySQL ?

1 votes

@Pacerier, je ne connais pas bien MySQL, mais je serais sidéré si leur produit se comportait différemment des autres produits relationnels à cet égard. L'un des nouveaux produits de bases de données non relationnelles, comme noSQL, pourrait fonctionner selon un paradigme différent, mais je parie que MySQL est le même.

13voto

Philip Kelley Points 19032

Comme l'a dit Charles Bretana, "cela ne fait rien" -- rien en plus de ce qui est déjà fait.

Avez-vous déjà entendu parler des exigences "ACID" d'une base de données relationnelle ? Le "A" est l'abréviation d'Atomic, ce qui signifie que soit la déclaration fonctionne dans son intégralité, soit elle ne fonctionne pas - et ce, pendant l'exécution de la déclaration, pas de d'autres requêtes peuvent être effectuées sur les données concernées par cette requête. BEGIN TRANSACTION / COMMIT "étend" cette fonctionnalité de verrouillage au travail effectué par des déclarations multiples, mais n'ajoute rien aux déclarations uniques.

Cependant, le journal des transactions de la base de données est siempre écrites lorsqu'une base de données est modifiée (insertion, mise à jour, suppression). Ce n'est pas une option, un fait qui a tendance à irriter les gens. Oui, il y a des bizarreries avec les insertions en masse et les modes de récupération, mais la base de données est toujours écrite.

Je vais également citer des niveaux d'isolation. Le fait de jouer avec cela aura un impact sur les commandes individuelles, mais cela ne rendra pas une requête déclarée-transaction enveloppée différente d'une requête "autonome". (Notez qu'elles peuvent être très puissantes et très dangereuses avec des transactions déclarées à plusieurs états). Notez également que "nolock" ne no s'appliquent aux insertions/mises à jour/suppressions -- ces actions ont toujours nécessité des verrous.

0 votes

@Philip, Thx, en recherchant votre commentaire, j'ai découvert que les choses ont changé pour 'Bulk Insert' depuis la dernière fois que j'ai examiné cette fonctionnalité (SQL 7 ou SQL2k) ...

1 votes

Mais deux requêtes autonomes exécutées dans une seule commande sans transaction explicite du code s'exécuteraient comme deux transactions implicites dans la base de données avec tout ce que cela signifie en termes de niveaux d'isolation et de données sales/écrites.

5voto

Gary Points 21

Pour moi, le fait d'intégrer une seule déclaration dans une transaction signifie que je peux revenir en arrière si, par exemple, j'oublie une clause WHERE lors de l'exécution d'une déclaration UPDATE manuelle et unique. Cela m'a sauvé plusieurs fois.

par exemple

--------------------------------------------------------------
CREATE TABLE T1(CPK INT IDENTITY(1,1) NOT NULL, Col1 int, Col2 char(3));
INSERT INTO T1 VALUES (101, 'abc');
INSERT INTO T1 VALUES (101, 'abc');
INSERT INTO T1 VALUES (101, 'abc');
INSERT INTO T1 VALUES (101, 'abc');
INSERT INTO T1 VALUES (101, 'abc');
INSERT INTO T1 VALUES (101, 'abc');
INSERT INTO T1 VALUES (101, 'abc');

SELECT * FROM T1

--------------------------------------------------------------
/* MISTAKE SCENARIO     (run each row individually) */
--------------------------------------------------------------
BEGIN TRAN YOUR_TRANS_NAME_1;   /* open a trans named YOUR_TRANS_NAME_1 */
    UPDATE T1 SET COL2 = NULL;  /* run some update statement */
    SELECT * FROM T1;       /* OOPS ... forgot the where clause */
ROLLBACK TRAN YOUR_TRANS_NAME_1;    /* since it did bad things, roll it back */
    SELECT * FROM T1;       /* tans rolled back, data restored. */

--------------------------------------------------------------
/* NO MISTAKES SCENARIO (run each row individually) */
--------------------------------------------------------------

BEGIN TRAN YOUR_TRANS_NAME_2;
    UPDATE T1 SET COL2 = 'CBA' WHERE CPK = 4;   /* run some update statement */
    SELECT * FROM T1;               /* did it correctly this time */

COMMIT TRAN YOUR_TRANS_NAME_2           /* commit (close) the trans */

--------------------------------------------------------------

DROP TABLE T1

--------------------------------------------------------------

5 votes

Peut-être que ma question n'était pas claire. Je faisais référence à un code comme : begin tran ; update foo set col1 = null ; commit tran ; qui est exécuté en un seul lot. Il s'agit d'un modèle très courant dans plusieurs bases de code que j'ai maintenues et il est également courant de le voir lorsque vous tracez le sql qu'une application existante émet. Vous décrivez un processus interactif qui est exécuté en deux étapes distinctes.

1 votes

Ce site est vrai pour les déclarations exécutées manuellement dans un outil de traitement de requêtes, car en démarrant explicitement une transaction, l'outil exige que vous commitiez explicitement (ou fassiez un retour en arrière), au lieu de le faire automatiquement.

2voto

flussence Points 5870

Une excuse possible est que cette seule déclaration pourrait entraîner l'exécution d'un tas d'autres requêtes SQL via des déclencheurs, et qu'ils se protègent contre quelque chose qui tournerait mal, bien que je m'attende à ce que tout SGBD ait le bon sens d'utiliser déjà les transactions implicites de la même manière.

L'autre chose à laquelle je pense est que certaines API permettent de désactiver l'autocommit, et que le code est écrit au cas où quelqu'un le ferait.

1 votes

Les triggers du serveur SQL s'exécutent à l'intérieur d'une transaction implicite du code DML qui les a déclenchés. Et oui, MS SQL vous permet de désactiver l'autocommit. Voir : msdn.microsoft.com/fr/us/library/aa259220(SQL.80).aspx

2voto

Quassnoi Points 191041

Lorsque vous démarrez une transaction explicite et émettez un DML Les ressources verrouillées par l'instruction restent verrouillées et les résultats de l'instruction ne sont pas visibles de l'extérieur de la transaction tant que vous ne l'avez pas validée ou annulée manuellement.

Voici ce dont vous pouvez avoir besoin ou non.

Par exemple, vous pouvez vouloir montrer des résultats préliminaires au monde extérieur tout en gardant un œil sur eux.

Dans ce cas, vous lancez une autre transaction qui place une demande de verrouillage avant que la première transaction ne soit validée, évitant ainsi la condition de course.

Les transactions implicites sont commitées ou annulées immédiatement après l'exécution de la transaction. DML se termine ou échoue.

0 votes

Ah, une différence subtile. Mais ce n'est pas vraiment un avantage des transactions explicites, je pense que le temps supplémentaire que les transactions explicites mettent à verrouiller une seule déclaration serait une situation clairement perdante/perdante - moins de performance et moins de concurrence, bien que probablement pour quelques millisecondes.

1 votes

@MatthewMartin : Je n'ai rien dit des avantages ou des inconvénients, j'ai juste expliqué la différence. Les transactions ne sont pas toutes liées aux performances. Par exemple, vous pouvez vouloir montrer des résultats préliminaires au monde extérieur tout en gardant un verrou sur eux. Dans ce cas, vous démarrez une autre transaction qui placera une demande de verrouillage avant que la première ne soit validée, évitant ainsi les conditions de course. Dans ce cas, vous devez toujours envelopper cette déclaration unique dans une transaction.

0 votes

Le serveur SQL ne prend pas en charge les véritables transactions imbriquées. En lancer une autre est une mauvaise idée. sqlskills.com/BLOGS/PAUL/post/

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X