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

#16 José Antonio Muñoz
03/02/2009 - 09:07 | Informe spam
Estoy de acuerdo contigo pero llevo la aplicación muy avanzada y tengo unos
plazos que cumplir y no me puedo plantear ahora rediseñar la aplicación.
Para una próxima aplicación tendré en cuenta vuestros consejos y plantearé
el tema de los bloqueos de otra manera.

Gracias y saludos,
José Antonio Muñoz.

"Jose Mariano Alvarez"
escribió en el
mensaje de noticias
news:
Jose:

Por que no incluyes banderas o flags en los registros para evitar que lo
accedan en ese momento en lugar de querer bloquear los registros.
Creo que deberias resolver tus problemas desde el punto de vista del
diseño y no forzar a la base de datos a hacer cosas para las cuales el
modelo relacional no esta preparado.
Creo que tarde o temprano vas a encontrar un problema que no vas a poder
resolver si sigues por ese camino, independientemente de la base de datos
relacional que uses.


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.










"José Antonio Muñoz" wrote in message
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.

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
#17 Jesús
03/02/2009 - 12:30 | Informe spam
"José Antonio Muñoz" escribió en el mensaje de
noticias news:
Correcto Jesús, ¡impedir que se efectuen lecturas sucias!.



No sé si estarás enterado de que a partir de SQL Server 2005 existen dos
nuevos niveles de aislamiento:

* READ COMMITTED SNAPSHOT
* SNAPSHOT

Con estos niveles de aislamiento un usuario podría ver las filas modificadas
y bloqueadas de forma exclusiva por otro usuario que aún no están
confirmadas, sin producirse lecturas sucias. El usuario vería la última
versión confirmada de las filas.

Esto podría ser una solución para permitir ver las filas modificadas sin
incurrir en lecturas sucias. Eso de que "no puedes verlo porque otro usuario
está trabajando con ello" no me gusta demasiado, prefiero darle una vista de
como estaban los datos antes de que empezara a trabajar con ello. Al fin y
al cabo ese "estaban" es en realidad "están", puesto que los cambios aún no
se han confirmado.

De todas formas bloquear registros por una aplicación no creo que sea una
mala práctica, yo lo estoy haciendo desde los tiempos del "clipper" y el
"basic" y era entonces una herramienta básica a la hora de programas
aplicaciones en red. Cada herramienta de programación tenía sus métodos
para el bloqueo de registros y de tablas.



¿Te refieres a lo que dijo Carlos o a lo que dije yo?

En cualquier caso lo que es una mala práctica es "que la duración de los
bloqueos de los recursos de SQL Server esté bajo el control de los usuarios"

Por ejemplo esto es mala práctica:

BEGIN TRANSACTION

UPDATE ...

INSERT ...

...
COMMIT

En cuanto al proceso del análisis, es posible que volviendo a resiseñar la
aplicación para resolver los problemas de control check-in y check-out
sería una solución pero llevo la aplicación ya muy avanzada para ello y el
bloqueo (ya resuelto) me resuelve el problema.




¿Y qué me dices de la detección de los conflictos de concurrencia? Es decir,
detectar si ha habido cambios en las filas e invalidar el proceso en tal
caso.
¿Cuantas veces al año se produce tal cosa?
Si los usuarios tienen bien repartido y asignado el trabajo, eso no debería
producirse nunca o casi nunca, y por tanto esto sería la mejor solución.
Los datasets y dataadapters, LINQ to SQL y Entity Framework ya tienen
incorporado mecanismos de detección de conflictos de concurrencia.
¿Introducir estos mecanismos haría que no cumplieras los plazos de entrega?

Gracías por vuestras sugerencias y un saludo,
José Antonio Muñoz.

"Jesús" escribió en el mensaje de
noticias news:%
Hola Carlos,

Mi respuesta venía sobre todo a cuento del párrafo:

"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"

Sobre todo de la frase "Cualquier cambio en esos datos,...,puede
invalidar el proceso". Creo sinceramente que esa frase describe
perfectamente el problema de José Antonio Muñoz. ¿Por qué si no José
Antonio iba a bloquear las filas sino es para impedir que se modificaran?
y ¿Por qué no quiere que los demás usuarios las vean? Pues creo que
porque han sido modificadas, aún no están confirmadas y respresentan un
estado de la base de datos no consistente desde el pundo de vista del
negocio. Creo que la intención de José Antonio es la de impedir lecturas
sucias a los demás usuarios.

Y ante eso pues propongo dos soluciones:

1) Detectar que ha habido cambios e invalidar el proceso
2) Implentar un mecanismo de check-in y check-out, que impida que se
produzca ese cambio en los datos. Como has mencionado, se trata
básicamente de una implementación de bloqueos a nivel de aplicación, lo
cual lo considero mejor alternativa que bloquear recursos en el servidor
con control de su duración por parte del usuario.


Lo de los estados, transiciones de estados y restricciones en las
transiciones de estados, aunque entiendo más o menos lo que quieres
decir, no termino de encajarlo en el contexto. También creo que eso puede
ser un análisis válido que explique por qué "Cualquier cambio en esos
datos,...,puede invalidar el proceso".

Pero pienso que sea lo que sea lo que explique por qué "Cualquier cambio
en esos datos,...,puede invalidar el proceso" las soluciones que he
propuesto funcionarían..

Espero que al final podamos entendernos.

Un saludo:

Jesús López


"Carlos M. Calvelo" escribió en el mensaje de
noticias
news:
Hola Jesús,

Parece que no me he explicado bien. No me refería a técnicas para
bloqueo, sino a un análisis del proceso del que habla José Antonio.

Una entidad puede recorrer una serie de estados (piensa en diagramas
de estados) donde el paso de un estado a otro corresponde a una
transacción completa.
Cualquier estado intermedio en el proceso no es un bloqueo sino
que solo expresa donde se encuentra esa entidad en el proceso y,
por medio de restricciones de transición, a que otros estatos
puede pasar. El que una entidad esté en un determinado estado
intermedio en un proceso no bloquea a nadie y puede estar en ese
estado todo el tiempo que sea necesario. Solo dice qué es lo que
se puede hacer con esa entidad, independientemente de quien o
qué haya inicializado el proceso.

Me dió la impresión que quizás José Antonio pueda reconsiderar
ese proceso en esos términos.

Por cierto, buena idea la del check-in / check-out. Como en los
sistemas de control de versiones de código fuente.
Con su 'expiration date' y todo. :) Aunque en control de
concurrencia no debería estar en manos de la(s) aplicación(es).

En todo caso, espero haberme explicado mejor ahora.

Saludos,
Carlos



Respuesta Responder a este mensaje
#18 Jose Mariano Alvarez
03/02/2009 - 13:43 | Informe spam
Suerte, luego nos cuentas como te fue.



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.










"José Antonio Muñoz" wrote in message
news:
Estoy de acuerdo contigo pero llevo la aplicación muy avanzada y tengo
unos plazos que cumplir y no me puedo plantear ahora rediseñar la
aplicación. Para una próxima aplicación tendré en cuenta vuestros consejos
y plantearé el tema de los bloqueos de otra manera.

Gracias y saludos,
José Antonio Muñoz.

"Jose Mariano Alvarez"
escribió en el
mensaje de noticias
news:
Jose:

Por que no incluyes banderas o flags en los registros para evitar que lo
accedan en ese momento en lugar de querer bloquear los registros.
Creo que deberias resolver tus problemas desde el punto de vista del
diseño y no forzar a la base de datos a hacer cosas para las cuales el
modelo relacional no esta preparado.
Creo que tarde o temprano vas a encontrar un problema que no vas a poder
resolver si sigues por ese camino, independientemente de la base de datos
relacional que uses.


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.










"José Antonio Muñoz" wrote in message
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.

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









email Siga el debate Respuesta Responder a este mensaje
Ads by Google
Help Hacer una pregunta AnteriorRespuesta Tengo una respuesta
Search Busqueda sugerida