2011-01-04 20 views

Respuesta

11
BEGIN TRAN 

    SELECT 1 
    FROM Table 
    WITH (XLOCK, ROWLOCK) 

COMMIT TRAN 

Eso hará el truco.

EDITAR

Como han dicho otros, no se puede bloquear una fila para no ser leído. La única forma que conozco de hacer esto es como sigue:

WITH (UPDLOCK, TABLOCK) 

Y esto es suponiendo que un CON (NOLOCK) nunca se usa en una instrucción SELECT (que debe evitarse en cualquier caso).

He probado esto y funcionará, aunque TABLOCK solo debe usarse en casos extremos. Ciertamente, si se requiere concurrencia, es una mala solución y se necesitaría alguna otra forma de bloqueo. Una forma es actualizar una columna de bit "Disponible Verdadero/Falso" y solo leer las filas donde Disponible = Verdadero. Como @gbn sugirió, READPAST podría usarse con esto.

+1

Acabo de probar esto, y XLOCK funciona tan bien como UPDLOCK para seleccionar. también vea: http://sqlblog.com/blogs/louis_davidson/archive/2006/12/13/does-xlock-always-prevent-reads-by-others.aspx –

+0

Sí, tiene razón. Sin embargo, con razón o sin razón, creo que el OP está buscando un bloqueo exclusivo porque dijeron que quieren "prevenir el CRUD". No sé si esto solo va en contra de las actualizaciones, o incluye el bloqueo de filas que se han leído. Así que opté por el bloqueo exclusivo. Si no está en contra de las filas que se han leído, entonces 100% usaría UPDLOCK. – IamIC

+0

+1 @KM gracias por el enlace. ¡Interesante! – IamIC

5

pruebe a usar la ROWLOCK y UPDLOCK dentro de una transacción de algo como esto:

BEGIN TRANSACTION 

SELECT @ID = ID 
FROM YourTable WITH (ROWLOCK, UPDLOCK) 
WHERE .... 

--more-- 

COMMIT TRANSACTION 

sin embargo no se puede evitar que un SELECT que utiliza la sugerencia NOLOCK de "sucio" de leer esto.

+0

UPDLOCK no impedirá las lecturas. – IamIC

+0

@ IanC, el título de la pregunta es ** Cómo bloquear exclusivamente una fila que impide la operación CRUD ** –

+0

@KM Lo sé. "Cómo bloquear * exclusivamente *" = XLOCK. :-) – IamIC

1

SQL Server ya bloquea de forma nativa un registro de lecturas sucias a medida que se actualiza. Esto tiene el efecto de bloquear la llamada de selección hasta que se complete la llamada de actualización/inserción.

+0

Aunque la afirmación es verdadera, el uso de SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED (o especificando NOLOCK) seguirá generando lecturas sucias. –

0

Es posible bloquear una fila usando una sugerencia de bloqueo CON (ROWLOCK); sin embargo, una instrucción SELECT siempre puede evitarla agregando una sugerencia de bloqueo CON (NOLOCK) que proporcionará una lectura sucia.

+0

Esto no es verdad. CON XLOCK, ROWLOCK garantizará un bloqueo de lectura en una fila. Fuera de interés, NOLOCK está en desuso. – IamIC

+0

En realidad, es verdad. Mi ejemplo usa ROWLOCK, no XLOCK. Sin embargo, una prueba simple demostrará que un NOLOCK aún devolverá las filas contra una mesa con un bloqueo exclusivo. comienzan tran seleccionar * de mesa con (xlock, rowlock) donde primarykeyid = 1 Usando otra conexión: seleccionar * de mesa con (nolock), donde primarykeyid = 1 La segunda instrucción de selección sigue devolviendo filas, aunque existe un bloqueo exclusivo en la fila seleccionada. –

+0

+1, esto funcionará tan bien como la respuesta de @ IanC –

1

Así como ROWLOCK, XLOCK según lo sugerido por otra gente, yo consideraría READPAST además

Esto permite que permite que otros lectores y escritores para saltar la cerradura de esta fila. Esto puede aumentar la concurrencia porque el bloqueo establecido por ROWLOCK, el bloqueo de XLOCK de lo contrario

+1

Buen punto, aunque el OP debería tener en cuenta que este salto significa omitir por completo las filas bloqueadas, ya que no aparecerán en los resultados, que pueden o no ser deseados. – IamIC

+0

Me gusta bastante la idea de READPAST porque permitirá al desarrollador la posibilidad de no encontrar la fila y, por lo tanto, continuar sin que se produzca un estancamiento. – Gwasshoppa

Cuestiones relacionadas