Puis-je ouvrir une transaction stoppable avec SQL Server?

Je cherche quelque chose de similaire à une transaction SQL. J'ai besoin des protections habituelles que les transactions fournissent, mais je ne veux pas que cela ralentisse quelqu'un d'autre.

Imaginez que le client A se connecte à la database et exécute ces commands:

BEGIN TRAN SELECT (something) (Wait a few seconds maybe.) UPDATE (something) COMMIT 

Entre le SELECT et le UPDATE, le client B arrive et tente de faire une requête qui, dans des circonstances normales, finirait par attendre que A soit COMMIT.

Ce que j'aimerais, c'est que le client A ouvre sa transaction de telle manière que B arrive et fasse sa requête, le client A finda sa transaction immédiatement annulée et ses commands suivantes échoueront. Le client B ne connaitrait qu'un timeout minimal.

(Notez que SELECT et UPDATE sont simplement des commands illustratives.)

Mettre à jour…

J'ai une tâche de haute priorité (client B) qui parfois (une fois par mois-ish) reçoit une erreur de timeout d'attente SQL, et une tâche de faible priorité (client A) avec une transaction qui provoque ce timeout. Je préférerais que la tâche de faible priorité échoue et soit réessayée au prochain cycle.

J'ai fini par résoudre ce problème en éliminant entièrement les transactions et en les remplaçant par un set informel de drapeaux. Les requêtes ont été refactorisées pour ne faire quelque chose que si le bon set de drapeaux est levé et j'ai ajouté quelque chose qui a effacé les loggings abandonnés que la restauration aurait effacés dans le passé.

J'ai corrigé mes problèmes de transaction en éliminant les transactions.

Bien qu'il ne s'agisse pas d'une transaction , Optimistic Concurrency peut être utile – il est utilisé par défaut dans LINQ2SQL, etc.

L'idée générale est que datatables sont lues – les modifications peuvent être faites de manière indépendante – et ensuite datatables sont réécrites avec un "contrôle" (ceci est vaguement comparable à un Comparaison et un Echange). Si la vérification échoue, c'est à l'application de décider quoi faire (redémarrer le process, continuer quand même, échouer).

Cela ne fonctionne naturellement pas pour tous les scénarios et peut ne pas détecter un certain nombre d'interactions, telles que de nouveaux éléments ajoutés entre «lire» et «écrire». La lecture et l'écriture peuvent toutes deux être dans des transactions séparées avec le niveau d'isolement approprié; les transactions séparées peuvent permettre l'entrelacement de transactions supplémentaires.

Bien sûr, en fonction du problème et des interactions exactes … différents niveaux d'isolation et / ou un locking à grain plus fin peuvent être suffisants.

Codage heureux.

L'utilisation du niveau d'isolement SNAPSHOT empêche B de bloquer. B verra datatables dans l'état où elles se trouvaient avant la publication de BEGIN TRANSACTION . À less que B modifie datatables, elles ne se bloqueront jamais.

C'est de return à l'avant.

Vous ne pouvez pas avoir des clients plus tard avortant des transactions antérieures: c'est le chaos.

Vous pouvez avoir une isolation de snapshots pour que le client B ait une vue cohérente et ne soit pas bloqué (surtout) par le client A. Aussi Wikipédia pour des choses plus générales

Peut-être décririez-vous votre problème plus complètement afin que nous puissions offrir des suggestions pour cela …

Une chose que j'ai vu utilisé (mais j'ai peur de ne pas avoir de code à scope de main) est que la transaction A engendre un autre process qui surveille ensuite la transaction. S'il voit des blocs causés par la transaction, il KILL immédiatement un KILL au spid.

Si je peux find le code pour cela, je l'appendai ici.