Uso de SPID en tablas de base de datos (en lugar de variable de tabla)

8

Base de datos transaccional utilizada para reservar cosas ...

Se le pidió a nuestro proveedor que reemplazara #temptables por @tablevariables (debido a los bloqueos de compilación pesados), pero en su lugar lo reemplazaron con una tabla real que agrega SPID como una columna para garantizar que el procedimiento almacenado solo actúe en las filas correspondientes.

¿Ves algún riesgo en este método de operación? Antes de que todas las transacciones se aislaran dentro de su propia transacción ... Me preocupaba que pudiéramos terminar bloqueando esta tabla un montón, pero su opinión es que SQL usa el bloqueo a nivel de fila y esto no creará más bloqueos.

Versión de SQL Server: 2016 Enterprise - 13.0.5216.0


CREATE TABLE dbo.qryTransactions (
    ID int IDENTITY (0,1) NOT NULL CONSTRAINT pk_qryTransactions PRIMARY KEY CLUSTERED,
    spid int NOT NULL,
    OrderID int,
    ItemID int,
    TimeTransactionStart datetime,
    TimeTransactionEnd datetime,
...other fields
    )

CREATE INDEX idx_qryTransactions_spidID ON qryTransactions (spid, ID) INCLUDE (ItemID, OrderID, TimeTransactionStart, TimeTransactionEnd)

outjet
fuente
1
Depende. ¿Cuántas sesiones están usando la tabla simultáneamente, qué tan activas son dichas sesiones, cuántos registros hay dentro de la tabla, se eliminan o permanecen los registros de esta nueva tabla, etc.? 5 sesiones, no es gran cosa. 500 sesiones, es muy probable que te encuentres con un bloqueo que no verías con tablas / variables temporales locales para cada sesión.
John Eisbrener
¿Qué versión del servidor sql estás usando?
Anthony Genovese
2016 Enterprise - 13.0.5216.0
superada el
Los registros por sesión en la mesa de lanzamiento serán 1-50 ... se eliminarán, por lo que la tabla en sí misma probablemente no obtendrá más de 1,000 filas a la vez ... sesiones concurrentes probablemente alrededor de 50 ...
outjet
1
Si se ve obligado a seguir este camino (intente evitarlo), pensaría seriamente en particionar el valor spid, asegurándome de que la escalada de bloqueo en la tabla esté configurada en AUTO. Entonces, al menos, el borrado de los datos de un spid específico podría realizarse en una operación de cambio y truncamiento.
Jonathan Fite

Respuestas:

5

Un poco más de divagación de lo que cabe en un bloque de comentarios ... y quiero resaltar un comentario que hizo el OP en respuesta a la respuesta de Ray:

  • el proc primario (Common_InsertOrders_1) crea una tabla temporal
  • un proceso hijo (InsertOrders) consulta la tabla temporal
  • Se están viendo bloqueos de compilación para el proceso hijo (InsertOrders)

Saliendo en una ligera tangente por un minuto ... sobre lo que sucedería con este escenario es Sybase ASE ...

  • cada tabla temporal obtiene una identificación de objeto única (claro, la identificación del objeto podría reutilizarse en algún momento, pero esto es raro, y ciertamente no sucederá para sesiones concurrentes)
  • Sybase ASE normalmente forzará una recompilación en cada ejecución del proceso secundario debido al cambio en la identificación del objeto para la tabla temporal
  • Sybase ASE también forzará una recompilación del proceso hijo si ve que la estructura de la tabla temporal ha cambiado (por ejemplo, diferente número de columnas, diferentes nombres de columnas / tipos de datos / nulabilidad) entre invocaciones de procesos almacenados
  • las versiones más recientes de Sybase ASE tienen una configuración que (efectivamente) le dice al compilador que ignore los cambios en los identificadores de objeto de la tabla temporal, eliminando así la recompilación del proceso hijo (NOTA: las recompilaciones aún ocurrirán si la estructura de la tabla cambia)

Volver a la edición del OP (bloqueos de compilación en el proceso hijo) ...

  • ¿Existe la posibilidad de que algunos vestigios del comportamiento de Sybase ASE aún puedan residir en SQL Server (desde cuando los dos productos eran guisantes en una vaina)?
  • ¿hay alguna configuración de SQL Server que pueda reducir (eliminar) las recompilaciones del proceso secundario (si se debe a cambios en la identificación del objeto)?
  • ¿Puede el OP verificar que el proceso padre está creando la tabla temporal con la misma estructura / DDL exacta cada vez?

En cuanto a la idea de usar una sola tabla permanente con @@ SPID para diferenciar filas entre sesiones ... estado allí, visto que ... qué asco ; problemas recurrentes:

  • cómo / cuándo limpiar filas huérfanas
  • La reutilización de @@ SPID por el motor de la base de datos podría generar problemas de precisión de datos si existen datos huérfanos (o durante la limpieza de datos huérfanos, por ejemplo, eliminar donde @@ SPID = 10 pero hay una sesión nueva / actual / activa con @ @ SPID = 10 => la limpieza elimina demasiados datos)
  • potencial para la escalada de bloqueos de bloqueos de fila a bloqueos de página / tabla
  • si la tabla tiene índices, entonces el bloqueo potencial (b) al actualizar los índices
  • dependiendo de la base de datos en la que reside la tabla, podría estar buscando mucha más actividad para escribir en el dispositivo de registro (en Sybase ASE es posible, efectivamente, deshabilitar el registro en tempdb)
  • incluso los bloqueos de nivel de fila (exclusivos) pueden bloquear otras sesiones (depende del nivel de aislamiento y de si una sesión puede escanear o saltarse dichos bloqueos exclusivos)

Me gustaría volver y (re) investigar el problema raíz (bloqueos de compilación en el proceso secundario) y ver si hay una manera de reducir (¿eliminar?) Dichos bloqueos de compilación. [Lamentablemente, mi conocimiento de SQL Server sobre estos temas es ... NULO ... por lo que estaría interesado en la información de algunos expertos en compiladores de SQL Server.]

markp-fuso
fuente
1
Estoy de acuerdo, creo que se debe dedicar más tiempo a investigar los bloqueos de compilación. Esto tiene algunos puntos para investigar. support.microsoft.com/en-us/help/263889/…
Jonathan Fite
8

Me parece que usar algo @@SPIDasí es pedir problemas.

Las ID de sesión se reutilizan con frecuencia; tan pronto como una conexión de usuario cierre sesión, esa ID de sesión estará disponible para ser utilizada nuevamente, y es probable que la próxima sesión que intente conectarse la use.

Para que funcione al menos de forma semi confiable, necesitaría un desencadenador de inicio de sesión que purgue las filas anteriores de la tabla con el mismo @@SPID. Si haces eso, es probable que veas muchos bloqueos en la tabla usando la @@SPIDcolumna.

SQL Server sí usa el bloqueo de filas, pero también usa el bloqueo de páginas y el bloqueo de tablas. Por supuesto, es posible que pueda mitigar eso mediante una buena indexación, pero esto todavía me parece un antipatrón.

Si el procedimiento almacenado es el único método utilizado para acceder a las tablas afectadas, puede investigar el uso de un bloqueo de la aplicación, sp_getapplockesencialmente para serializar el acceso a las partes relevantes. Los documentos para sp_getapplock están aquí . Erik Darling tiene una publicación interesante al respecto aquí .

Max Vernon
fuente
4

Sí, veo riesgos. Es ingenuo contar con SQL utilizando el bloqueo de filas. Por ejemplo, estoy bastante seguro de que las inserciones y eliminaciones usarán bloqueos de página al menos. SQL Engine elige el tipo de bloqueo en función de varios factores y ninguno de esos factores incluye "su opinión". Las soluciones generales, como cambiar las tablas temporales a variables de tabla, generalmente también son malas ideas. Las variables de tabla son muy útiles en algunas situaciones, pero tienen limitaciones y problemas de rendimiento. Prefiero tablas temporales en la mayoría de las circunstancias. Particularmente cuando la mesa tendrá más de unas pocas docenas de filas. Solicitaría al proveedor que explique por qué el sistema experimentó "bloqueos de compilación pesados" y cómo eso degradó el rendimiento. Recuerde, cada vez que mire encontrará "cerraduras pesadas" de algún tipo. Eso no significa necesariamente que las cerraduras sean un problema. Max ' Los comentarios sobre @@ SPID también son importantes. Además, el modelo de transacción y el procesamiento de errores podrían ser grandes problemas. Si su sistema experimenta puntos muertos o problemas de calidad de los datos de entrada, entonces el procesamiento de error estándar puede dar lugar a la finalización de la sesión sin que la tabla qryTransactions se restablezca correctamente. En mi opinión, el enfoque de solución incorrecta para el problema original.

Rayo
fuente
Gracias por la respuesta - a sus puntos: nuestros rastros muestran que LCK espera mucho para un bloqueo de compilación en InsertOrders de procedimiento almacenado. Hay un procedimiento principal Common_InsertOrders_1 que declara la tabla temporal #qryTransactions y luego el procedimiento anidado InsertOrders_2 consulta la tabla temporal. Además, hemos aprendido también es frecuente recompilación porque después de 6 modificaciones a una tabla temporal vacío, ningún procedimiento almacenado que hace referencia a que tendrá que volver a compilar tabla temporal
outjet
Hay muchas razones por las que se recompilará un procedimiento o una declaración. MarkP mencionó varios de ellos que se aplican en SyBase y estoy seguro de que SQL Server es similar. El recuento de filas de la tabla temporal es un buen ejemplo y la recompilación no es necesariamente algo malo. Las estadísticas de la tabla pueden cambiar sustancialmente el Plan de consulta óptimo y se requiere una compilación para determinarlo. Pero quiero volver a repetir. SIEMPRE habrá un bloqueo superior y eso no significa que el bloqueo sea un problema. A menos que vea otra evidencia de un problema de rendimiento, no se preocupe.
Ray