Quand exactement plusieurs utilisateurs ne peuvent-ils pas exécuter simultanément une procédure stockée avec une table temporaire?

9

J'ai une question concernant un document sur les tables temporaires que j'ai récemment lu sur TechNet . Le quatrième paragraphe de la section Tables temporaires de cette page se lit comme suit:

Si une table temporaire est créée avec une contrainte nommée et que la table temporaire est créée dans le cadre d'une transaction définie par l'utilisateur, un seul utilisateur à la fois peut exécuter l'instruction qui crée la table temporaire. Par exemple, si une procédure stockée crée une table temporaire avec une contrainte de clé primaire nommée, la procédure stockée ne peut pas être exécutée simultanément par plusieurs utilisateurs.

Je travaille dans un environnement où nous utilisons de manière significative une poignée de procédures stockées qui utilisent des tables temporaires indexées, et nous n'avons jamais rencontré de problème où les utilisateurs doivent attendre la fin d'une exécution avant le début de la suivante. J'espère que cela continuera d'être le cas, mais je crains que cela ne devienne un problème si cette mise en garde n'est pas bien comprise.

Plus précisément, je ne suis pas clair sur les points suivants:

  1. Cela s'applique-t-il uniquement aux tables temporaires globales ou aux tables locales? Il semble étrange qu'une table qui n'est pas visible en dehors de la session (comme dans ce dernier cas) empêche une autre session de s'exécuter simultanément.
  2. Qu'est-ce qui constitue une "contrainte nommée"? Toutes les contraintes n'ont-elles pas de noms (même si elles sont générées par le système)? S'agit-il de contraintes avec un alias défini par l'utilisateur? Cela me semble une mauvaise formulation.
  3. Est-ce que "plusieurs utilisateurs" signifie en réalité plusieurs sessions? Ces procédures sont appelées via notre application à l'aide d'un seul compte de service, donc 99,9% des appels à nos scripts sont effectués vers la base de données par ce compte unique (et je ne suis pas préoccupé par l'appel occasionnel qu'un administrateur peut faire sur le backend). Si le compte de service peut exécuter le sproc dans plusieurs sessions simultanément, ce problème est sans objet pour mes besoins.
Wesley Marshall
la source
1
Vous mentionnez que vos tables temporaires sont indexées mais la question concerne les contraintes. Les index ne sont pas des contraintes. Ce qui est vrai pour l'un peut ou peut ne pas être vrai pour l'autre. Dans ce cas, les noms d'index peuvent être dupliqués dans une base de données, contrairement aux contraintes. Les noms d'index ne peuvent pas être dupliqués sur une seule table. Les index nommés n'entraîneront donc pas les problèmes nommés contraintes.
Shannon Severance
@Shannon, en effet, au moment où j'ai écrit la question, j'avais ce point confus. Je pense que l'utilisation prolifique de PRIMARY KEY CLUSTERED vs. PRIMARY KEY que j'ai vue dans des exemples de code et de documentation m'a amené à croire que les index cluster sont des contraintes. Et, par extension, inférer que tous les index sont des contraintes. J'ai fait une lecture légère l'après-midi plus tôt, ce qui m'a éclairé.
Wesley Marshall

Réponses:

10

Je pense à cela car vous ne pouvez pas avoir de noms en double tempdb.sys.key_constraints. Voici le contenu de cette vue de métadonnées sur l'un de mes serveurs:

vue initiale

Tous les noms impairs qui se terminent par _6E...étaient des noms générés automatiquement par SQL Server. Ce ne sont pas des contraintes nommées car je ne leur ai pas explicitement donné de nom lors de leur création. SQL Server génère un nom de contrainte dans les coulisses qui évite en théorie les collisions de noms.

Si j'essaie de créer le tableau suivant en deux sessions différentes:

create table #x1 (
ID INT NOT NULL,
CONSTRAINT NAMED_CONSTRAINT_1 PRIMARY KEY (ID)
);

Celui qui s'exécute en deuxième lance une erreur:

Msg 2714, niveau 16, état 5, ligne 1

Il existe déjà un objet nommé 'NAMED_CONSTRAINT_1' dans la base de données.

Msg 1750, niveau 16, état 1, ligne 1

Impossible de créer une contrainte ou un index. Voir les erreurs précédentes.

Retrouver la vue:

avec contrainte

Si j'essaie de créer le tableau suivant en deux sessions, il n'y a pas de problème:

create table #y1 (
ID INT NOT NULL,
PRIMARY KEY (ID)
);

Voici la vue des métadonnées:

avec des contraintes par défaut

Juste pour répondre directement à vos questions: la partie que vous avez citée s'applique aux tables temporaires locales et globales, une contrainte nommée est une contrainte dans laquelle vous lui donnez délibérément un nom, et plusieurs utilisateurs signifient plusieurs sessions.

Joe Obbish
la source
11

Cela s'applique aux tables temporaires locales.

La différence entre les contraintes nommées et non nommées est la suivante:

CREATE TABLE #t1 (c1 INT PRIMARY KEY CLUSTERED)

CREATE TABLE #t2 (c1 INT,
                     CONSTRAINT pk_c1 PRIMARY KEY  CLUSTERED(c1) )

Laisser les contraintes de nom du système rend extrêmement improbable une collision. Dans cet exemple, si vous ouvrez deux fenêtres dans SSMS, vous pourrez créer les #t1deux, mais pas #t2.

Les tables temporaires globales sont partagées par tous les utilisateurs, vous devez donc gérer les choses différemment. Ils ne sont «détruits» que lorsque la dernière session est terminée en les utilisant, vous devez donc vous assurer que lorsque les utilisateurs y accèdent, ils ne peuvent accéder qu'à leurs données. Cela est parfois effectué par SPID, d'autres fois par une valeur de hachage. Cela dépend de la façon dont la table temporaire globale est utilisée.

En règle générale pour les tables temporaires globales, les procédures stockées vérifieront si elles existent, et seulement les créer si l' OBJECT_ID()est NULL.

Plusieurs utilisateurs signifient plusieurs sessions. Le nom de connexion n'a rien à voir avec cela. Si George s'exécute sp_something @i = 1et Gina s'exécute sp_something @i = 2, peu importe s'ils sont tous deux connectés en tant que User1, ils auront des SPID différents.

Erik Darling
la source