Bloqueo de registros en SQL Server 2008

30/01/2009 - 10:12 por José Antonio Muñoz | Informe spam
Hola al grupo,

Estoy desarrollando una aplicación con SQL Server para gestionar 5 puestos
en red. Estoy intentando analizar como se bloquean filas individuales y
también en grupo. Para bloquear filas individuales estoy utilizando las
sugerencias de consulta WITH (ROWLOCK, HOLDLOCK, UPDLOCK) en la cláusula
FROM de una consulta y parece ser que funciona correctamente, al intentar
abrir un recordset en una transacción bloquea la fila correspondiente a la
consulta y el resto de usuarios no pueden abrir en otra transacción la misma
fila. Sin embargo cuando intento ejecutar una consulta que me devuelve
varias filas me bloquea toda la tabla y no las filas individuales.

¿Como puedo solucionar este problema?

Saludos,
José Antonio Muñoz.

Preguntas similare

Leer las respuestas

#6 Jose Mariano Alvarez
02/02/2009 - 13:41 | Informe spam
No me queda claro el motivo de bloquear la visibilidad de registros mientras
otro usuario los esta viendo.
Coincido con Gux, por que no utilizas un update masivo en lugar de un
registro por vez?

La tabla tiene PK?
Si es asi, usted no puede tener inconvenientes ya que un update por PK solo
deberia bloquear el registro que actualiza.


Saludos


Ing. Jose Mariano Alvarez
SQLTotal Consulting

(Cambia los ceros por O y saca lo que sobra)

Este mensaje se proporciona tal como es, SIN GARANTIAS de ninguna clase. Por
favor tratar de indicar la versión de SQL y Service Pack. La inclusión de
(CREATE, INSERTS, etc.) para poder reproducir el problema también ayuda.










"Gustavo Larriera (MVP)"
wrote in message news:
Hola José Antonio Muñoz,

"José Antonio Muñoz" wrote:

Yo tengo una tabla que tiene un campo que se repite según unas
determinadas
condiciones. Si un usuario necesita modificar los registros cuyo valor de
ese campo sea 1 (puede haber varios registros) primero hago un SELECT
para
ver que registros que son y uno por uno voy modificando con la
instrucción
UPDATE.



Cuando usted dice "uno por uno voy modificando" se refiere a que usa un
cursor? O cómo es que usted hace esa modificación fila por fila?

NOTA: Solo cuando el campo correspondiente sea clave y no se repita el
bloqueo si funciona correctamente, es decir, que puedo hacer un SELECT
cuyo
valor sea 1 y solo me recupera un registro. Otro usuario intenta hacer
SELECT a ese registro y no puede ya que da un error de bloqueo. Pero si
hace
un SELECT de otro registro, por ejemplo, el 2 y si puede.




Puede usted mostrar la estructura de la tabla y los índices que hay
creados
para ella?

Saludos
~gux

Respuesta Responder a este mensaje
#7 Jesús
02/02/2009 - 15:02 | Informe spam
"José Antonio Muñoz" escribió en el mensaje de
noticias news:%23Bf%
Hola Gustavo,

He mirado los artículos que me has enviado y son interesantes, muchas
gracias por ello, sin embargo no resulve mi problema. Te explico:

Yo tengo una tabla que tiene un campo que se repite según unas
determinadas condiciones. Si un usuario necesita modificar los registros
cuyo valor de ese campo sea 1 (puede haber varios registros) primero hago
un SELECT para ver que registros que son y uno por uno voy modificando con
la instrucción UPDATE. Otro usuario puede modicar otros registros con otro
valor de campo y así sucesivamente con muchos usuarios.



¿Por qué hay que hacer primero un SELECT y luego un UPDATE registro a
registro?

¿No sería mejor hacer sólo esto?

UPDATE Tabla SET Campo = @Valor
WHERE EseCampo = 1

Yo necesito bloquear todos los registros seleccionados por el usuario X
para que nadie pueda modificar (ni siquiera ver con un SELECT)



La cuestión es. ¿Por qué?

Uno de los problemas que me encuentro cuando voy a hacer consultorías a los
clientes es que no se puede acceder a la base de datos y realizar
operaciones porque las cosas están bloqueadas. ¿Y tú quieres bloquear?

Esa manera de bloquear las cosas que estás intentando se llama "bloqueo
pesimista" y hace ya mucho tiempo que está visto que es un enfoque bastante
malo. Hay otras maneras de controlar la concurrencia que bloquear y
bloquear, como por ejemplo el "bloqueo optimista".

esos registros sin embargo he probado con los diferentes niveles de
aislamiento y los diferentes Hits de bloqueos pero no me funciona ya que o
bloquea todos los registros de la tabla y por tanto los demas usuarios no
pueden hacer su SELECT correspondiente para modificar o no me bloquea
ningún registro y por ello todo el mundo ve los registros incluso los
bloqueados.

NOTA: Solo cuando el campo correspondiente sea clave y no se repita el
bloqueo si funciona correctamente, es decir, que puedo hacer un SELECT
cuyo valor sea 1 y solo me recupera un registro. Otro usuario intenta
hacer SELECT a ese registro y no puede ya que da un error de bloqueo. Pero
si hace un SELECT de otro registro, por ejemplo, el 2 y si puede.

Saludos,
José Antonio Muñoz.

"Gustavo Larriera (MVP)"
escribió en el mensaje de noticias
news:
Espero que estos artículos le sean útiles. El primero es algo viejo pero
las
ideas aún sirven. El segundo apunta al BOL donde se explica cómo se usa
SET
TRANSACTION ISOLATION para configurar el nivel de aislamiento que desee.

Lo habitual es usar el nivel READ COMMITTED o el nivel REPEATABLE READ.
Pero
cuál usar depende de lo que sus transacciones necesiten hacer.

Locking in Microsoft SQL Server
http://www.mssqlcity.com/Articles/A...0Locks.htm


SET TRANSACTION ISOLATION LEVEL (Transact-SQL)
http://msdn.microsoft.com/en-us/lib...73763.aspx

Gustavo Larriera, Microsoft MVP
http://www.linkedin.com/in/gustavolarriera
Este mensaje se proporciona tal como es, sin garantías de ninguna clase.



"José Antonio Muñoz" wrote:

¿Cómo puedo establecer el SERIALIZATION LEVEL para automatizar el
bloqueo de
registros y de tablas?

saludos,
José Antonio Muñoz

"Gustavo Larriera (MVP)"
escribió en el mensaje de noticias
news:
> Seré curioso: Por qué desea usted indicarle a SQL Server lo qué cosas
> deberá
> lockear, en vez de permitirle que lo haga en forma automática acorde
> al
> SERIALIZATION LEVEL que se haya establecido?
>
> Gustavo Larriera, Microsoft MVP
> http://www.linkedin.com/in/gustavolarriera
> Este mensaje se proporciona tal como es, sin garantías de ninguna
> clase.
>
>
>
> "José Antonio Muñoz" wrote:
>
>> Hola al grupo,
>>
>> Estoy desarrollando una aplicación con SQL Server para gestionar 5
>> puestos
>> en red. Estoy intentando analizar como se bloquean filas individuales
>> y
>> también en grupo. Para bloquear filas individuales estoy utilizando
>> las
>> sugerencias de consulta WITH (ROWLOCK, HOLDLOCK, UPDLOCK) en la
>> cláusula
>> FROM de una consulta y parece ser que funciona correctamente, al
>> intentar
>> abrir un recordset en una transacción bloquea la fila correspondiente
>> a
>> la
>> consulta y el resto de usuarios no pueden abrir en otra transacción
>> la
>> misma
>> fila. Sin embargo cuando intento ejecutar una consulta que me
>> devuelve
>> varias filas me bloquea toda la tabla y no las filas individuales.
>>
>> ¿Como puedo solucionar este problema?
>>
>> Saludos,
>> José Antonio Muñoz.
>>
>>







Respuesta Responder a este mensaje
#8 José Antonio Muñoz
02/02/2009 - 18:06 | Informe spam
El proceso es bastante complejo como para explicarlo aquí en el foro, se
trata de una aplicación donde a través de una tabla principal que se compone
de muchos campos (más de 100 campos) y muchos de estos campos se actualizan
a partir de muchas tablas maestras (en total pueden existir más de 50
tablas). El usuario necesita tener bloqueado un grupo determinado de
registros que a su vez está modificando otras tablas en un orden
determinado, claro si hay que actualizar muchos datos con fórmulas,
procesos, validaciones, etc., y, además, se requieren varios formularios de
entrada de datos es por lo que es necesario el bloqueo, para que otro
usuario no pueda tocar ni ver esos datos mientras están en el proceso que he
explicado anteriormente. Simplemente es así, no hay otra forma, ya que
durante la actualización de estos registros se generan datos intermedios que
reflejarían un estado que no se correspondería con la realidad cuando el
otro usuario intenta consultar esos mismos datos en otro terminal.

No sé si me he explicado bien. De todas formas hoy mismo, probando, he
generado un índice "noclustered" y no "único" a partir del campo en cuestión
y "vualá" el problema se ha solucionado de golpe. Parece ser que en el
bloqueo de registros de SQL server intervienen los índices.

Muchas gracias por vuestra colaboración.

Saludos,
José Antonio Muñoz.

"Gustavo Larriera (MVP)"
escribió en el mensaje de noticias
news:
Hola José Antonio Muñoz,

"José Antonio Muñoz" wrote:

Yo tengo una tabla que tiene un campo que se repite según unas
determinadas
condiciones. Si un usuario necesita modificar los registros cuyo valor de
ese campo sea 1 (puede haber varios registros) primero hago un SELECT
para
ver que registros que son y uno por uno voy modificando con la
instrucción
UPDATE.



Cuando usted dice "uno por uno voy modificando" se refiere a que usa un
cursor? O cómo es que usted hace esa modificación fila por fila?

NOTA: Solo cuando el campo correspondiente sea clave y no se repita el
bloqueo si funciona correctamente, es decir, que puedo hacer un SELECT
cuyo
valor sea 1 y solo me recupera un registro. Otro usuario intenta hacer
SELECT a ese registro y no puede ya que da un error de bloqueo. Pero si
hace
un SELECT de otro registro, por ejemplo, el 2 y si puede.




Puede usted mostrar la estructura de la tabla y los índices que hay
creados
para ella?

Saludos
~gux

Respuesta Responder a este mensaje
#9 Jesús
02/02/2009 - 21:32 | Informe spam
Realmente es una mala práctica mantener bloqueados recursos dejando al
usuario el control de cuando se liberan dichos recursos.


"José Antonio Muñoz" escribió en el mensaje de
noticias news:%
El proceso es bastante complejo como para explicarlo aquí en el foro, se
trata de una aplicación donde a través de una tabla principal que se
compone de muchos campos (más de 100 campos) y muchos de estos campos se
actualizan a partir de muchas tablas maestras (en total pueden existir más
de 50 tablas). El usuario necesita tener bloqueado un grupo determinado de
registros que a su vez está modificando otras tablas en un orden
determinado, claro si hay que actualizar muchos datos con fórmulas,
procesos, validaciones, etc., y, además, se requieren varios formularios
de entrada de datos es por lo que es necesario el bloqueo, para que otro
usuario no pueda tocar ni ver esos datos mientras están en el proceso que
he explicado anteriormente. Simplemente es así, no hay otra forma, ya que
durante la actualización de estos registros se generan datos intermedios
que reflejarían un estado que no se correspondería con la realidad cuando
el otro usuario intenta consultar esos mismos datos en otro terminal.




Sí existe otra forma. Hasta que no se haya finalizado el proceso no haces
ninguna modificación en la base de datos. Toda la información intermedia la
vas almacenado en otro sitio como por ejemplo en memoria, en tablas
intermedias, o donde quieras. Cuando tengas toda la información necesaria
para realizar el proceso completo empiezas una transacción, haces todas las
modificaciones a la base de datos que tengas que hacer y confirmas la
transacción. De esta manera la duración de los bloqueos no está bajo el
control del usuario, durará lo que tarde en ejecutarse las intrucciones
SQL..


No sé si me he explicado bien. De todas formas hoy mismo, probando, he
generado un índice "noclustered" y no "único" a partir del campo en
cuestión y "vualá" el problema se ha solucionado de golpe. Parece ser que
en el bloqueo de registros de SQL server intervienen los índices.

Muchas gracias por vuestra colaboración.

Saludos,
José Antonio Muñoz.

"Gustavo Larriera (MVP)"
escribió en el mensaje de noticias
news:
Hola José Antonio Muñoz,

"José Antonio Muñoz" wrote:

Yo tengo una tabla que tiene un campo que se repite según unas
determinadas
condiciones. Si un usuario necesita modificar los registros cuyo valor
de
ese campo sea 1 (puede haber varios registros) primero hago un SELECT
para
ver que registros que son y uno por uno voy modificando con la
instrucción
UPDATE.



Cuando usted dice "uno por uno voy modificando" se refiere a que usa un
cursor? O cómo es que usted hace esa modificación fila por fila?

NOTA: Solo cuando el campo correspondiente sea clave y no se repita el
bloqueo si funciona correctamente, es decir, que puedo hacer un SELECT
cuyo
valor sea 1 y solo me recupera un registro. Otro usuario intenta hacer
SELECT a ese registro y no puede ya que da un error de bloqueo. Pero si
hace
un SELECT de otro registro, por ejemplo, el 2 y si puede.




Puede usted mostrar la estructura de la tabla y los índices que hay
creados
para ella?

Saludos
~gux




Respuesta Responder a este mensaje
#10 Carlos M. Calvelo
02/02/2009 - 23:15 | Informe spam
Hola Jesús, José Antonio,

On 2 feb, 21:32, Jesús wrote:
Realmente es una mala práctica mantener bloqueados recursos dejando al
usuario el control de cuando se liberan dichos recursos.



Cierto. Muy mala práctica.
No debe haber la más mínima interacción con el usuario dentro
de una transacción.



"José Antonio Muñoz" escribió en el mensaje de
noticiasnews:%

> El proceso es bastante complejo como para explicarlo aquí en el foro, se
> trata de una aplicación donde a través de una tabla principal que se
> compone de muchos campos (más de 100 campos) y muchos de estos campos se
> actualizan a partir de muchas tablas maestras (en total pueden existir más
> de 50 tablas). El usuario necesita tener bloqueado un grupo determinado de
> registros que a su vez está modificando otras tablas en un orden
> determinado, claro si hay que actualizar muchos datos con fórmulas,
> procesos, validaciones, etc., y, además, se requieren varios formularios
> de entrada de datos es por lo que es necesario el bloqueo, para que otro
> usuario no pueda tocar ni ver esos datos mientras están en el proceso que
> he explicado anteriormente. Simplemente es así, no hay otra forma, ya que
> durante la actualización de estos registros se generan datos intermedios
> que reflejarían un estado que no se correspondería con la realidad cuando
> el otro usuario intenta consultar esos mismos datos en otro terminal.

Sí existe otra forma. Hasta que no se haya finalizado el proceso no haces
ninguna modificación en la base de datos. Toda la información intermedia la
vas almacenado en otro sitio como por ejemplo en memoria, en tablas
intermedias, o donde quieras. Cuando tengas toda la información necesaria
para realizar el proceso completo empiezas una transacción, haces todas las
modificaciones a la base de datos que tengas que hacer y confirmas la
transacción. De esta manera la duración de los bloqueos no está bajo el
control del usuario, durará lo que tarde en ejecutarse las intrucciones
SQL..





Yo presiento que el problema de José Antonio es más complejo que
eso. Los datos de entrada (input) de ese proceso no vienen solo
de la aplicación sino también de la base de datos misma. Cualquier
cambio en esos datos, por ejemplo a causa de acciones de otros
usuarios, puede invalidar el proceso. Y ese proceso no equivale
a una transación, sino a una serie de transaciones.
Me explico:

A mi me dá la impresión que el problema que tiene José Antonio es
de análisis de ese proceso y de (re)diseño de la base de datos para
poder acomodarlo. Estoy pensando en que los registros implicados
(entidades o como quiera llamarsele) pueden tener que pasar por una
serie de estados donde cada paso de un estado a otro de los
siguientes posibles sí puede considerarse como una transacción en
el sentido que se está hablando aquí. Todas esas entidades pueden
estar en cualquier estado en cualquier momento y la base de datos
estar en un estado consistente en cuanto a integridad de datos. Lo
que está o no permitido hacer con esas entidades dependería
naturalmente del estado en que se encuentren (restricciones de
transición). También es posible que sea necesario que ese proceso
'lleve consigo' todos los datos de entrada necesarios y que
pertenecen al proceso (una copia de los originales al inicio del
proceso).

Solo unas ideas generales por lo que presiento 'entre líneas' en
lo que describe José Antonio. Pero puede que mi intuición me engañe.

Saludos,
Carlos
Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaSiguiente AnteriorRespuesta Tengo una respuesta
Search Busqueda sugerida