¿Cuándo exactamente varios usuarios no pueden ejecutar simultáneamente un procedimiento almacenado con una tabla temporal?

9

Tengo una pregunta sobre una pieza de documentación sobre tablas temporales que leí recientemente en TechNet . El cuarto párrafo de la sección de Tablas temporales en esa página dice lo siguiente:

Si se crea una tabla temporal con una restricción con nombre y la tabla temporal se crea dentro del alcance de una transacción definida por el usuario, solo un usuario a la vez puede ejecutar la instrucción que crea la tabla temporal. Por ejemplo, si un procedimiento almacenado crea una tabla temporal con una restricción de clave primaria nombrada, el procedimiento almacenado no puede ser ejecutado simultáneamente por múltiples usuarios.

Trabajo en un entorno donde hacemos un uso significativo de un puñado de procedimientos almacenados que usan tablas temporales indexadas, y nunca hemos encontrado un problema en el que los usuarios tengan que esperar a que se complete una ejecución antes de que comience la siguiente. Espero que siga siendo así, pero me preocupa que pueda convertirse en un problema si esta advertencia no se entiende correctamente.

Específicamente, no estoy claro sobre los siguientes puntos:

  1. ¿Esto se aplica solo a las tablas temporales globales, o también a las locales? Parece extraño que una tabla que no sea visible fuera de la sesión (como en el último caso) impida que otra sesión se ejecute simultáneamente.
  2. ¿Qué califica como una "restricción con nombre"? ¿No todas las restricciones tienen nombres (incluso si son generados por el sistema)? ¿Se refiere esto a restricciones con un alias definido por el usuario? Esto me parece una frase pobre.
  3. ¿"Usuarios múltiples" en realidad significa sesiones múltiples? Estos procedimientos se llaman a través de nuestra aplicación utilizando una sola cuenta de servicio, por lo que el 99.9% de las llamadas a nuestros scripts se realizan a la base de datos por esa cuenta única (y no me preocupa la llamada ocasional que un administrador puede hacer en el back-end). Si la cuenta de servicio puede ejecutar el sproc en varias sesiones simultáneamente, entonces este problema es discutible para mis propósitos.
Wesley Marshall
fuente
1
Usted menciona que sus tablas temporales están indexadas, pero la pregunta es sobre las contracciones. Los índices no son restricciones. Lo que es cierto para uno puede o no ser cierto para el otro. En este caso, los nombres de índice pueden duplicarse dentro de una base de datos, a diferencia de las restricciones. Los nombres de índice no se pueden duplicar en una sola tabla. Los denominados índices no causarán los problemas que las restricciones nombradas sí causarán.
Shannon Severance
@Shannon, de hecho, cuando escribí la pregunta, tenía este punto confundido. Creo que el uso prolífico de CLAVE PRIMARIA CLUSIFICADA versus CLAVE PRIMARIA que he visto en el código de muestra y en la documentación me llevó a creer que los índices agrupados son restricciones. Y, por extensión, inferir que todos los índices son restricciones. Hice un poco de lectura ligera por la tarde antes, lo que me aclaró.
Wesley Marshall

Respuestas:

10

Creo que no puedes tener nombres duplicados tempdb.sys.key_constraints. Esto es lo que hay en esa vista de metadatos en uno de mis servidores:

vista inicial

Todos los nombres impares que terminan con _6E...fueron generados automáticamente por SQL Server. No tienen restricciones de nombre porque no les di explícitamente un nombre al crearlas. SQL Server genera un nombre de restricción detrás de escena que, en teoría, evita las colisiones de nombres.

Si intento crear la siguiente tabla en dos sesiones diferentes:

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

El que se ejecuta en segundo lugar arroja un error:

Mensaje 2714, Nivel 16, Estado 5, Línea 1

Ya hay un objeto llamado 'NAMED_CONSTRAINT_1' en la base de datos.

Mensaje 1750, Nivel 16, Estado 1, Línea 1

No se pudo crear restricción o índice. Ver errores anteriores.

Mirando la vista nuevamente:

con restricción

Si intento crear la siguiente tabla en dos sesiones, no hay problema:

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

Aquí está la vista de metadatos:

con restricciones predeterminadas

Solo para responder a sus preguntas directamente: la parte que citó se aplica tanto a las tablas temporales locales como a las globales, una restricción con nombre es aquella en la que le da un nombre deliberadamente, y varios usuarios significan varias sesiones.

Joe Obbish
fuente
11

Esto se aplica a las tablas temporales locales.

La diferencia entre las restricciones con nombre y sin nombre es esta:

CREATE TABLE #t1 (c1 INT PRIMARY KEY CLUSTERED)

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

Dejar las restricciones de nombre del sistema hace que sea extremadamente improbable que haya una colisión. En este ejemplo, si abre dos ventanas en SSMS, podrá crear #t1en ambas, pero no #t2.

Las tablas temporales globales son compartidas por todos los usuarios, por lo que debe manejar las cosas de manera diferente. No se 'destruyen' hasta que la última sesión haya terminado de usarlos, por lo que debe asegurarse de que cuando los usuarios accedan a ellos, solo puedan acceder a sus datos. Esto a veces se realiza mediante SPID, otras veces mediante un valor hash. Depende de cómo se use la tabla temporal global.

Por lo general, para las tablas temporales globales, los procedimientos almacenados verifican si existen y luego solo los crean si OBJECT_ID()es así NULL.

Múltiples usuarios significa múltiples sesiones. El nombre de usuario no tiene nada que ver con eso. Si George corre sp_something @i = 1y Gina corre sp_something @i = 2, no importa si ambos están conectados User1, tendrán diferentes SPID.

Erik Darling
fuente