que tiene que hacer esto en la transacción para asegurar dos clientes simultáneos no insertará misma ValorDelCampo dos veces:
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRANSACTION
DECLARE @id AS INT
SELECT @id = tableId FROM table WHERE [email protected]
IF @id IS NULL
BEGIN
INSERT INTO table (fieldValue) VALUES (@newValue)
SELECT @id = SCOPE_IDENTITY()
END
SELECT @id
COMMIT TRANSACTION
también se puede utilizar para reducir el bloqueo Double-checked locking sobrecarga
DECLARE @id AS INT
SELECT @id = tableID FROM table (NOLOCK) WHERE [email protected]
IF @id IS NULL
BEGIN
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRANSACTION
SELECT @id = tableID FROM table WHERE [email protected]
IF @id IS NULL
BEGIN
INSERT INTO table (fieldValue) VALUES (@newValue)
SELECT @id = SCOPE_IDENTITY()
END
COMMIT TRANSACTION
END
SELECT @id
cuanto a por qué AISLAMIENTO dE NIVEL sERIALIZABLE es necesario, cuando se está dentro de una transacción serializable, la primera tha SELECT t golpea la mesa crea un bloqueo de rango que cubre el lugar donde debe estar el registro, para que nadie más pueda insertar el mismo registro hasta que finalice esta transacción.
Sin ISOLATION LEVEL SERIALIZABLE, el nivel de aislamiento predeterminado (READ COMMITTED) no bloquearía la tabla en el momento de la lectura, por lo que entre SELECT y UPDATE, alguien aún podría insertar. Las transacciones con nivel de aislamiento LECTURA COMPROMETIDA no provocan que SELECCIONAR se bloquee. Las transacciones con READATABLE READS bloquean el registro (si se encuentra) pero no el espacio.
¿Qué lenguaje de programación está utilizando? Esto podría hacerse mejor allí dentro de una transacción. –
posible duplicado de [Solo insertando una fila si no está ya allí] (http://stackoverflow.com/questions/3407857/only-inserting-a-row-if-its-not-already-there) –
Esta es la una pregunta más antigua; la pregunta 'Solo insertando una fila' debe cerrarse como un duplicado de esto, y no al revés. –