Tengo un procedimiento almacenado, que selecciona 1 registro de nuevo. el procedimiento almacenado podría llamarse desde varias aplicaciones diferentes en diferentes PC. La idea es que el procedimiento almacenado recupere el siguiente registro que debe procesarse, y si dos aplicaciones llaman al proceso almacenado al mismo tiempo, no se debe recuperar el mismo registro. Mi consulta está debajo, intento escribir la consulta de la manera más eficiente posible (sql 2008). ¿Se puede hacer de manera más eficiente que esto?Transacción eficiente, bloqueo de registros
CREATE PROCEDURE GetNextUnprocessedRecord
AS
BEGIN
SET NOCOUNT ON;
--ID of record we want to select back
DECLARE @iID BIGINT
-- Find the next processable record, and mark it as dispatched
-- Must be done in a transaction to ensure no other query can get
-- this record between the read and update
BEGIN TRAN
SELECT TOP 1
@iID = [ID]
FROM
--Don't read locked records, only lock the specific record
[MyRecords] WITH (READPAST, ROWLOCK)
WHERE
[Dispatched] is null
ORDER BY
[Received]
--Mark record as picked up for processing
UPDATE
[MyRecords]
SET
[Dispatched] = GETDATE()
WHERE
[ID] = @iID
COMMIT TRAN
--Select back the specific record
SELECT
[ID],
[Data]
FROM
[MyRecords] WITH (NOLOCK, READPAST)
WHERE
[ID] = @iID
END
No estoy convencido de que esto TSQL es transaccionalmente seguro ... –
intente poner WAITFOR DELAY '0: 2: 0' después del SELECT y antes de la ACTUALIZACIÓN, ejecute el SP y ejecute el mismo SP desde otra conexión ... –
en realidad, ¡estoy equivocado! El HOLDLOCK tiene el mismo efecto que REPEATABLEREAD en la tabla MyRecords. –