with sirve que para lock index funcion español sql-server database sql-server-2005 tsql concurrency

sql server - sirve - ¿Cómo uso las sugerencias de bloqueo para que dos consultas paralelas devuelvan resultados no intersecantes?



sql server with nolock español (3)

¿Qué tal algo así?

UPDATE TOP (1) Tasks SET State = Processing OUTPUT INSERTED.RetrievedTaskId WHERE State = ReadyForProcessing

pruébalo:

DECLARE @Tasks table (RetrievedTaskId int, State char(1)) INSERT @Tasks VALUES (1,''P'') INSERT @Tasks VALUES (2,''P'') INSERT @Tasks VALUES (3,''R'') INSERT @Tasks VALUES (4,''R'') UPDATE TOP (1) @Tasks SET State = ''P'' OUTPUT INSERTED.RetrievedTaskId WHERE State = ''R'' SELECT * FROM @Tasks

--SALIDA:

RetrievedTaskId --------------- 3 (1 row(s) affected) RetrievedTaskId State --------------- ----- 1 P 2 P 3 P 4 R (4 row(s) affected)

Tengo una tabla SQL Tasks con columnas Id y State . Necesito hacer lo siguiente: encontrar cualquier tarea con estado ReadyForProcessing , recuperar todas sus columnas y establecer su estado en Processing . Algo así como (pseudocódigo):

BEGIN TRANSACTION; SELECT TOP 1 * FROM Tasks WHERE State = ReadyForProcessing // here check if the result set is not empty and get the id, then UPDATE Tasks SET State = Processing WHERE TaskId = RetrievedTaskId END TRANSACTION

Esta consulta se ejecutará en paralelo desde varios clientes de bases de datos y la idea es que si dos clientes ejecutan la consulta en paralelo adquieren tareas diferentes y nunca la misma tarea.

Parece que necesito pistas de bloqueo. He leído este artículo de MSDN pero no entiendo nada allí. ¿Cómo uso los consejos de bloqueo para resolver el problema anterior?


Esto debería funcionar.

BEGIN TRANSACTION DECLARE @taskId SELECT TOP (1) @taskid = TaskId FROM Tasks WITH (UPDLOCK, READPAST) WHERE State = ''ReadyForProcessing'' UPDATE Tasks SET State = ''Processing'' WHERE TaskId = @taskid COMMIT TRAN


Realmente, realmente no me gusta el bloqueo explícito en las bases de datos, es una fuente de todo tipo de errores locos, y el rendimiento de la base de datos puede caer por el suelo.

Sugeriría que se vuelva a escribir el SQL en las siguientes líneas:

begin transaction; update tasks set state = processing where state = readyForProcessing and ID = (select min(ID) from tasks where state = readyForProcessing); commit;

De esta manera, no necesita bloquear nada, y dado que la actualización es atómica, no hay riesgo de que dos procesos actualicen el mismo registro.