J'ai une procédure stockée qui sélectionne essentiellement les valeurs d'une table et les insère dans une autre, une sorte d'archivage. Je veux éviter que plusieurs personnes le fassent en même temps.
Pendant que cette procédure est en cours d'exécution, je ne veux pas que quelqu'un d'autre puisse la démarrer, mais je ne veux pas de sérialisation, l'autre personne exécutera la procédure une fois que j'en aurai fini.
Ce que je veux, c'est que l'autre personne essayant de le démarrer obtienne une erreur pendant que j'exécute la procédure.
J'ai essayé d'utiliser sp_getapplock, mais je n'arrive pas à empêcher complètement la personne d'exécuter la procédure.
J'ai également essayé de trouver la procédure avec sys.dm_exec_requests et de bloquer la procédure, alors que cela fonctionne, je pense que ce n'est pas optimal car sur certains serveurs, je n'ai pas les autorisations pour exécuter sys.dm_exec_sql_text (sql_handle).
Quelle est la meilleure façon pour moi de le faire?
la source
Réponses:
Pour ajouter à la réponse de @ Tibor-Karaszi, la définition d'un délai d'expiration de verrouillage ne produit pas réellement d'erreur (j'ai soumis un PR contre les documents). sp_getapplock renvoie simplement -1, vous devez donc vérifier la valeur de retour. Alors comme ça:
la source
Utilisez sp_getapplock au début du processus et définissez un délai de verrouillage sur une valeur très faible. De cette façon, vous obtenez une erreur lorsque vous êtes bloqué.
la source
Une autre option consiste à créer une table pour contrôler l'accès à la procédure. l'exemple ci-dessous montre un tableau possible ainsi qu'une procédure qui pourrait l'utiliser.
la source
IsLocked
état à 0 dans ce cas? Je suis également curieux de savoir si vous l'utilisezCOALESCE
ici. Peut@@ROWCOUNT
être nul après des instructions commeUPDATE
? Enfin, juste un petit coup de pouce, pourquoi mettre un point-virgule devant laTHROW
déclaration dans ce cas spécifique?Je pense que vous essayez de résoudre le problème d'une manière incorrecte. Ce que vous voulez, c'est une protection maximale de la cohérence de la base de données. Si deux personnes exécutent une procédure stockée en même temps, la cohérence de la base de données peut être violée.
Pour se protéger contre divers types d'incohérences de base de données, la norme SQL a quatre niveaux d'isolement des transactions:
Cependant, la norme SQL a une approche basée sur le verrouillage pour ces incohérences de base de données, et pour des raisons de performances, de nombreuses bases de données adoptent une approche basée sur l'isolement d'instantané qui a essentiellement ces niveaux:
Les annulations de transactions dans ces bases de données basées sur l'isolement d'instantané peuvent sembler inquiétantes, mais là encore, chaque base de données annulera une transaction en raison d'un blocage, de sorte que toute application raisonnable doit de toute façon être en mesure de réessayer une transaction.
Ce que vous voulez, c'est le niveau d'isolement SERIALISABLE : il garantit que si les transactions exécutées indépendamment les unes après les autres aboutissent à un bon état, toute exécution parallèle des transactions se traduit également par un bon état. Heureusement, Michael Cahill a découvert dans sa thèse de doctorat comment le niveau d'isolement SERIALISABLE peut être supporté par des bases de données instantanées isolées avec peu d'effort.
Si vous utilisez un niveau d'isolement SERIALIZABLE dans une base de données isolée par instantané, si deux personnes tentent d'exécuter la procédure stockée simultanément et qu'elles se mettent sur les pieds l'une de l'autre, l'une des transactions est annulée.
Désormais, SQL Server prend-il réellement en charge le niveau d'isolement SERIALIZABLE (au lieu de masquer l'isolement d'instantané derrière le mot clé SERIALIZABLE )? Franchement, je ne sais pas: la seule base de données que je connaisse qui le supporte est PostgreSQL.
Même si je n'ai pas donné de conseils spécifiques à SQL Server, je poste quand même cette réponse, car les utilisateurs de PostgreSQL et les utilisateurs d'autres bases de données qui peuvent envisager de passer à PostgreSQL peuvent bénéficier de ma réponse. De plus, les utilisateurs de bases de données non PostgreSQL qui ne peuvent pas passer à PostgreSQL peuvent faire pression sur leur fournisseur de base de données préféré pour offrir un véritable niveau d'isolement SERIALISABLE .
la source
Je me rends compte que le «vrai» problème peut être plus complexe.
Dans le cas contraire: si vous effectuez votre archivage avec des déclencheurs d'insertion et / ou de mise à jour, vous pouvez éviter le problème que vous essayez de résoudre.
J'espère que ça aide,
-Chris C.
la source
the 'real' problem may be more complex
. Dans le cas contraire, les déclencheurs sont une bonne solution. De plus, il sera probablement plus facile à tester et à maintenir car il s'agit d'une fonctionnalité de la base de données au lieu d'une solution personnalisée.