Tengo el requisito de crear un procedimiento almacenado que emule una secuencia TSQL. Es decir, siempre da un valor entero distinto y creciente en cada llamada. Además, si se pasa un entero, debe devolver ese valor si nunca ha habido un resultado mayor o el siguiente entero más alto disponible. No hace falta decir que puede haber varios clientes llamando a este SP al mismo tiempo.
Dada una tabla MetaInfo con columnas MetaKey varchar (max) y MeatValueLong bigInt. Se espera que la fila con la MetaKey de 'Internal-ID-Last' contenga el último valor más alto asignado. Creé el siguiente procedimiento almacenado:
CREATE PROCEDURE [dbo].[uspGetNextID]
(
@inID bigInt
)
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRANSACTION
UPDATE MetaInfo WITH (ROWLOCK)
SET MetaValueLong = CASE
WHEN ISNULL(MetaValueLong,0) > @inID THEN MetaValueLong+1
ELSE @inID+1
END
WHERE MetaKey = 'Internal-ID-Last'
SELECT MetaValueLong
FROM MetaInfo
WHERE MetaKey = 'Internal-ID-Last'
COMMIT TRANSACTION
END
Mi pregunta es simplemente: ¿funciona este procedimiento almacenado como se esperaba (a todas las personas que llamen se les asignará un resultado único)?
fuente
Respuestas:
He echado un vistazo y los propios MS ofrecen una solución sin bloqueos
http://blogs.msdn.com/b/sqlcat/archive/2006/04/10/sql-server-sequence-number.aspx
Esta es una actualización simple sin sugerencias de bloqueo, pero dicen que bloquea / bloquea.
No hay mucho en SO sobre esto tampoco.
Me inclinaría a agregar UPDLOCK a su ROWLOCK (según "table as a queue" (SO) pero sin READPAST). Esto aumentará el aislamiento en caso de que un segundo proceso comience a leer.
Sin embargo, el hecho de que todos sus procesos quieran leer / escribir la misma fila me hace dudar de mí mismo. READPAST permite concurrencia segura, pero en este caso es inútil.
Nota: puede usar la cláusula OUTPUT en lugar de una segunda selección, entonces no necesita la transacción.
HTH ...
fuente
Falta lo siguiente
Sí, debe cumplir con su condición. Una vez que tales situaciones surgen en las transacciones, crea sus múltiples instancias y, posteriormente, a todos los que llaman se les asignará un resultado único
fuente
Una solución más escalable que no requiere serialización es esta:
fuente