Quando esattamente più utenti non sono in grado di eseguire contemporaneamente una procedura memorizzata con una tabella temporanea?


9

Ho una domanda su un pezzo di documentazione sulle tabelle temporanee che ho letto di recente su TechNet . Il quarto paragrafo della sezione Tabelle temporanee su quella pagina recita come segue:

Se viene creata una tabella temporanea con un vincolo denominato e la tabella temporanea viene creata nell'ambito di una transazione definita dall'utente, solo un utente alla volta può eseguire l'istruzione che crea la tabella temporanea. Ad esempio, se una procedura memorizzata crea una tabella temporanea con un vincolo di chiave primaria denominato, la procedura memorizzata non può essere eseguita contemporaneamente da più utenti.

Lavoro in un ambiente in cui facciamo un uso significativo di una manciata di stored procedure che utilizzano tabelle temporanee indicizzate e non abbiamo mai riscontrato un problema in cui gli utenti devono attendere il completamento di un'esecuzione prima che inizi la successiva. Spero che continuerà ad essere il caso, ma temo che potrebbe diventare un problema se questo avvertimento non fosse compreso correttamente.

In particolare, non sono chiaro i seguenti punti:

  1. Questo vale solo per le tabelle temporanee globali o anche per quelle locali? Sembra strano che una tabella non visibile al di fuori della sessione (come in quest'ultimo caso) impedisca l'esecuzione simultanea di un'altra sessione.
  2. Cosa si qualifica come "vincolo denominato"? Non tutti i vincoli hanno nomi (anche se sono generati dal sistema)? Si riferisce a vincoli con un alias definito dall'utente? Questo mi sembra una frase scadente.
  3. "Utenti multipli" significa in realtà sessioni multiple? Queste procedure vengono chiamate tramite la nostra applicazione utilizzando un singolo account di servizio, quindi il 99,9% delle chiamate ai nostri script vengono effettuate sul DB da quel singolo account (e non mi preoccupo della chiamata occasionale che un amministratore può effettuare sul back-end). Se l'account del servizio può eseguire lo sproc in più sessioni contemporaneamente, questo problema è discutibile per i miei scopi.

1
Dici che le tue tabelle temporanee sono indicizzate ma la domanda riguarda i contrasti. Gli indici non sono vincoli. Ciò che è vero per uno può o non può essere vero per l'altro. In questo caso, i nomi degli indici possono essere duplicati all'interno di un database, a differenza dei vincoli. I nomi degli indici non possono essere duplicati su una singola tabella. Quindi gli indici nominati non causeranno i problemi indicati dai vincoli.
Shannon Severance,

@Shannon, infatti, al momento in cui ho scritto la domanda, avevo questo punto confuso. Penso che l'uso prolifico di PRIMARY KEY CLUSTERED vs. PRIMARY KEY che ho visto nel codice di esempio e nella documentazione mi abbia portato a credere che gli indici cluster siano vincoli. E, per estensione, dedurre che tutti gli indici sono vincoli. Ho fatto qualche leggere lettura pomeridiana in precedenza che mi ha chiarito questo.
Wesley Marshall,

Risposte:


10

Ci penso perché non puoi avere nomi duplicati in tempdb.sys.key_constraints. Ecco cosa c'è in quella vista dei metadati su uno dei miei server:

vista iniziale

Tutti i nomi dispari che finiscono con _6E...erano nomi generati automaticamente da SQL Server. Non sono chiamati vincoli perché non li ho esplicitamente nominati durante la loro creazione. SQL Server genera un nome di vincolo dietro le quinte che in teoria evita le collisioni di nomi.

Se provo a creare la seguente tabella in due diverse sessioni:

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

Quello che esegue il secondo genera un errore:

Messaggio 2714, livello 16, stato 5, riga 1

Esiste già un oggetto denominato "NAMED_CONSTRAINT_1" nel database.

Messaggio 1750, livello 16, stato 1, riga 1

Impossibile creare vincolo o indice. Vedi gli errori precedenti.

Verifica di nuovo la vista:

con vincolo

Se provo a creare la seguente tabella in due sessioni non c'è problema:

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

Ecco la vista dei metadati:

con vincoli predefiniti

Solo per rispondere direttamente alle tue domande: la parte che hai citato si applica sia alle tabelle temporanee locali che globali, un vincolo denominato è quello in cui gli dai deliberatamente un nome e più utenti significa più sessioni.


11

Questo vale per le tabelle temporanee locali.

La differenza tra vincoli nominati e non nominati è questa:

CREATE TABLE #t1 (c1 INT PRIMARY KEY CLUSTERED)

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

Lasciare i vincoli del nome del sistema rende estremamente improbabile che ci sia una collisione. In questo esempio, se apri due finestre in SSMS, sarai in grado di creare #t1in entrambi, ma non #t2.

Le tabelle temporanee globali sono condivise da tutti gli utenti, quindi devi gestire le cose in modo diverso. Non vengono "distrutti" fino al termine dell'ultima sessione, quindi è necessario assicurarsi che quando gli utenti accedono ad essi possano accedere solo ai propri dati. Questo a volte viene fatto da SPID, altre volte da un valore hash. Dipende da come viene utilizzata la tabella delle temp globali.

In genere per le tabelle temporanee globali, le procedure memorizzate controllano se esistono e quindi le creano solo se lo OBJECT_ID()sono NULL.

Utenti multipli significa sessioni multiple. Il nome di accesso non ha nulla a che fare con esso. Se George corre sp_something @i = 1e Gina corre sp_something @i = 2, non importa se entrambi sono connessi come User1, avranno SPID diversi.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.