Evitar bloqueo tabla

21/12/2006 - 09:59 por Santiago Barro | Informe spam
Hola a todos,
tengo una tabla en donde sólo se van insertando y consultando registros.
Nunca se modifican.

Al realizar el proceso de inserción de datos se consulta a la vez un
servicio web, por lo que puede tardar algunos segundos en ejecutar la
inserción.
Al ser ejecutado dentro de una transacción me bloquea la tabla, con lo que
los demás usuarios pueden notar una pequeña espera hasta que se termina la
transacción antes de poder ejecutar la suya.

He visto que puedo utilizar "set transaction isolation level uncommitted"
para evitar el bloqueo y que los demás puedan insertar sus registros, pero
si los intento consultar me sigue bloqueada la tabla, a menos que en la
misma consulta también le indique "set transaction isolation level read
uncommitted".

¿Tengo que indicarlo en cada consulta?

He visto también que existe una opción "with (rowlock)" que parece que sólo
bloquea los registros en lugar de la tabla ¿es así?.

Muchas gracias y un saludo
Santiago Barro

Preguntas similare

Leer las respuestas

#1 Javier Loria
21/12/2006 - 12:02 | Informe spam
Hola Santiago:
Es un mito que las inserciones bloqueen la tabla, eso muy rara vez
ocurre. Mira el siguiente codigo que puedes pegar en una ventana de Query
Analizer o del SSMS:
CREATE TABLE DEMO(
Demo INT NOT NULL PRIMARY KEY
)
GO
BEGIN TRAN
INSERT Demo(Demo)
VALUES(1)
En otra ventana puedes hacer
SELECT * FROM Demo
Veras como el select no esta bloqueado y no veras las transacciones
porque no se les ha hecho commit. Este el el comportamiento default y se
llama READ COMMITED. El READ UNCOMMITED que sugieres producir resultados que
pueden ser falsos o incompletos ya que la transaccion puede hacer rollback.
Saludos,

Javier Loria
Costa Rica-MVP
Solid Quality Learning

"Santiago Barro" wrote in message
news:
Hola a todos,
tengo una tabla en donde sólo se van insertando y consultando registros.
Nunca se modifican.

Al realizar el proceso de inserción de datos se consulta a la vez un
servicio web, por lo que puede tardar algunos segundos en ejecutar la
inserción.
Al ser ejecutado dentro de una transacción me bloquea la tabla, con lo que
los demás usuarios pueden notar una pequeña espera hasta que se termina la
transacción antes de poder ejecutar la suya.

He visto que puedo utilizar "set transaction isolation level uncommitted"
para evitar el bloqueo y que los demás puedan insertar sus registros, pero
si los intento consultar me sigue bloqueada la tabla, a menos que en la
misma consulta también le indique "set transaction isolation level read
uncommitted".

¿Tengo que indicarlo en cada consulta?

He visto también que existe una opción "with (rowlock)" que parece que
sólo bloquea los registros en lugar de la tabla ¿es así?.

Muchas gracias y un saludo
Santiago Barro


Respuesta Responder a este mensaje
#2 Santiago Barro
21/12/2006 - 12:31 | Informe spam
Gracias Javier,
pero he probado tu código y el SELECT queda bloqueado hasta que hago un
COMMIT TRAN o ROLLBACK TRAN en el INSERT.

Si escribo "set transaction isolation level read uncommitted" antes del
BEGIN TRAN del INSERT, me pasa lo mismo.
Si, además, escribo "set transaction isolation level read uncommitted" antes
del SELECT, después sí que no bloquea nada y puedo consultar tranquilamente.

¿Sabes a qué puede ser debido?

Muchas gracias y un saludo
Santiago Barro


"Javier Loria" escribió en el mensaje
news:
Hola Santiago:
Es un mito que las inserciones bloqueen la tabla, eso muy rara vez
ocurre. Mira el siguiente codigo que puedes pegar en una ventana de Query
Analizer o del SSMS:
> CREATE TABLE DEMO(
Demo INT NOT NULL PRIMARY KEY
)
GO
BEGIN TRAN
INSERT Demo(Demo)
VALUES(1)
> En otra ventana puedes hacer
> SELECT * FROM Demo
> Veras como el select no esta bloqueado y no veras las transacciones
porque no se les ha hecho commit. Este el el comportamiento default y se
llama READ COMMITED. El READ UNCOMMITED que sugieres producir resultados
que pueden ser falsos o incompletos ya que la transaccion puede hacer
rollback.
Saludos,

Javier Loria
Costa Rica-MVP
Solid Quality Learning

"Santiago Barro" wrote in message
news:
Hola a todos,
tengo una tabla en donde sólo se van insertando y consultando registros.
Nunca se modifican.

Al realizar el proceso de inserción de datos se consulta a la vez un
servicio web, por lo que puede tardar algunos segundos en ejecutar la
inserción.
Al ser ejecutado dentro de una transacción me bloquea la tabla, con lo
que los demás usuarios pueden notar una pequeña espera hasta que se
termina la transacción antes de poder ejecutar la suya.

He visto que puedo utilizar "set transaction isolation level uncommitted"
para evitar el bloqueo y que los demás puedan insertar sus registros,
pero si los intento consultar me sigue bloqueada la tabla, a menos que en
la misma consulta también le indique "set transaction isolation level
read uncommitted".

¿Tengo que indicarlo en cada consulta?

He visto también que existe una opción "with (rowlock)" que parece que
sólo bloquea los registros en lugar de la tabla ¿es así?.

Muchas gracias y un saludo
Santiago Barro







Respuesta Responder a este mensaje
#3 Javier Loria
21/12/2006 - 14:24 | Informe spam
Hola Santiago:
Disculpa que lo que escribi fue una gran tonteria.
Lo que ocurre es lo siguiente, originalmente queria escribir que: las
inserciones NO bloquean la TABLA, solo la fila y la demostracion era:
=CREATE TABLE DEMO(
Demo INT NOT NULL PRIMARY KEY
)
GO
INSERT Demo(Demo)
SELECT 1 UNION ALL
SELECT 2 UNION ALL
SELECT 3 UNION ALL
SELECT 4
BEGIN TRAN
INSERT Demo(Demo)
VALUES(5)
=Y luego en otra consulta escribes:
=SELECT * FROM Demo WHERE Demo=3
= Con lo cual se demuestra que la tabla no se bloquea sino unicamente el
fila. Pero luego cuando estaba preparando el SELECT * FROM Demo para que se
demostrar que se quedaba bloqueado esperando la fila 5, para mi sorpresa
FUNCIONO DE MARAVILLA, sin bloquearse ni nada. Asi que decidi cambiar el
ejemplo para sinplificarlo muy contento de haber aprendido algo. Y asi se
fue el posteo anterior.
Lo que no habia tomado en cuenta la BD donde estaba probando el código
esta en SQL 2005 y tiene
configurado la opcion de ALLOW_SNAPSHOT_ISOLATION con lo cual el SELECT no
fija un shared lock sino que obtiene la ultima version consistente de datos
cuando inicio la transacción. De esto me di cuenta hasta que lei tu posteo e
hice un poco de investigacion sobre la BD.
Retomando tu problema de bloqueos, el rowlock no te ayuda porque siempre
el que modifica hace un bloqueo exclusivo y por default es por fila; solo
cuando hay muchas, muchas inserciones el servidor escalara a bloqueos de
pagina o de tabla. La solucion del cliente de usar READ UNCOMMITTED es
horrible porque lees transacciones incompletas y por los problemas de uso de
indices que provoca.
Si tienes SQL 2005 es facil porque puedes habilitar el SNAPSHOT
ISOLATION o todavia mas el READ COMMITED SNAPSHOT en la BD.
Pero el problema no esta en el que lee, sino en el que escribe, por lo
que lo mejor siempre es estudiar la transaccion que modifica los datos,
asegurarse que es lo mas corta posible, que no usa cursores, de preferencia
con transacciones controladas en el servidor, que los las tablas no esten
sobreindexadas, etc. Esto sirve para SQL 2000 y 20005.
Un saludos,

Javier Loria
Costa Rica-MVP
Solid Quality Learning

"Santiago Barro" wrote in message
news:%
Gracias Javier,
pero he probado tu código y el SELECT queda bloqueado hasta que hago un
COMMIT TRAN o ROLLBACK TRAN en el INSERT.

Si escribo "set transaction isolation level read uncommitted" antes del
BEGIN TRAN del INSERT, me pasa lo mismo.
Si, además, escribo "set transaction isolation level read uncommitted"
antes del SELECT, después sí que no bloquea nada y puedo consultar
tranquilamente.

¿Sabes a qué puede ser debido?

Muchas gracias y un saludo
Santiago Barro


"Javier Loria" escribió en el mensaje
news:
Hola Santiago:
Es un mito que las inserciones bloqueen la tabla, eso muy rara vez
ocurre. Mira el siguiente codigo que puedes pegar en una ventana de Query
Analizer o del SSMS:
>> CREATE TABLE DEMO(
Demo INT NOT NULL PRIMARY KEY
)
GO
BEGIN TRAN
INSERT Demo(Demo)
VALUES(1)
>> En otra ventana puedes hacer
>> SELECT * FROM Demo
>> Veras como el select no esta bloqueado y no veras las transacciones
porque no se les ha hecho commit. Este el el comportamiento default y se
llama READ COMMITED. El READ UNCOMMITED que sugieres producir resultados
que pueden ser falsos o incompletos ya que la transaccion puede hacer
rollback.
Saludos,

Javier Loria
Costa Rica-MVP
Solid Quality Learning

"Santiago Barro" wrote in message
news:
Hola a todos,
tengo una tabla en donde sólo se van insertando y consultando registros.
Nunca se modifican.

Al realizar el proceso de inserción de datos se consulta a la vez un
servicio web, por lo que puede tardar algunos segundos en ejecutar la
inserción.
Al ser ejecutado dentro de una transacción me bloquea la tabla, con lo
que los demás usuarios pueden notar una pequeña espera hasta que se
termina la transacción antes de poder ejecutar la suya.

He visto que puedo utilizar "set transaction isolation level
uncommitted" para evitar el bloqueo y que los demás puedan insertar sus
registros, pero si los intento consultar me sigue bloqueada la tabla, a
menos que en la misma consulta también le indique "set transaction
isolation level read uncommitted".

¿Tengo que indicarlo en cada consulta?

He visto también que existe una opción "with (rowlock)" que parece que
sólo bloquea los registros en lugar de la tabla ¿es así?.

Muchas gracias y un saludo
Santiago Barro












Respuesta Responder a este mensaje
#4 Gustavo Larriera (MVP)
22/12/2006 - 01:12 | Informe spam
Hola Santiago Barro,

Santiago Barro wrote:

Al realizar el proceso de inserción de datos se consulta a la vez un
servicio web, por lo que puede tardar algunos segundos en ejecutar la
inserción.
Al ser ejecutado dentro de una transacción me bloquea la tabla, con lo que
los demás usuarios pueden notar una pequeña espera hasta que se termina la
transacción antes de poder ejecutar la suya.



Voy a dar una opinión general ya que no dispongo de los detalles de lo
que estás haciendo.

En principio es una mala idea que el consumo de un web service esté
formando parte de una transacción. En la práctica, termina convirtiendo
a tu transacción en una transacción larga. Esta siempre es problemática
para los recursos del servidor d ebase de datos.

Deberías analizar si es posible consumir el WS fuera de la transacción.


Gustavo Larriera, MVP
Solid Quality
MVP profile: http://aspnet2.com/mvp.ashx?GustavoLarriera
Blog: http://solidqualitylearning.com/blogs/glarriera/
Este mensaje se proporciona tal como es, sin garantías de ninguna clase
/ This message is provided "AS IS" with no warranties expressed or
implied, and confers no rights.
Respuesta Responder a este mensaje
#5 Santiago Barro
22/12/2006 - 08:20 | Informe spam
Muchas gracias a los dos por vuestras opiniones,
supongo que teneis razón y será mejor realizar las consultas al servicio web
fuera de la transacción.

El problema es que antes de insertar cada fila, debo ejecutar un
procedimiento en un servicio web el cual me devuelve un valor de retorno que
debo guardar con la fila en mi base de datos.
Supongo que a nivel de rendimiento será mejor guardar los registros y
realizar un UPDATE después actualizando dicho valor de retorno.

Ya miraré cómo lo soluciono.

Muchas gracias de nuevo y un saludo.
Santiago Barro


"Gustavo Larriera (MVP)" escribió en el mensaje
news:
Hola Santiago Barro,

Santiago Barro wrote:

Al realizar el proceso de inserción de datos se consulta a la vez un
servicio web, por lo que puede tardar algunos segundos en ejecutar la
inserción.
Al ser ejecutado dentro de una transacción me bloquea la tabla, con lo
que los demás usuarios pueden notar una pequeña espera hasta que se
termina la transacción antes de poder ejecutar la suya.



Voy a dar una opinión general ya que no dispongo de los detalles de lo que
estás haciendo.

En principio es una mala idea que el consumo de un web service esté
formando parte de una transacción. En la práctica, termina convirtiendo a
tu transacción en una transacción larga. Esta siempre es problemática para
los recursos del servidor d ebase de datos.

Deberías analizar si es posible consumir el WS fuera de la transacción.


Gustavo Larriera, MVP
Solid Quality
MVP profile: http://aspnet2.com/mvp.ashx?GustavoLarriera
Blog: http://solidqualitylearning.com/blogs/glarriera/
Este mensaje se proporciona tal como es, sin garantías de ninguna clase /
This message is provided "AS IS" with no warranties expressed or implied,
and confers no rights.

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