¿como evitar los hot blocks?

04/05/2008 - 18:38 por AntonioFox | Informe spam
¿Que tal?

Estaba traspasando una clasica tabla de contadores (donde llevo contador
de facturas, documentos de venta, pedidos ...) a SQL Server y leo que
esta practica no es recomendada por el problema de los hot blocks

Entonses ¿que me recomienda para no tener el problema de los hot blocks
y como hago para tambien tener mis contadores? No me valen identities ya
que nesecito que me genere numeros realez

Gracias

AntonioFox

Preguntas similare

Leer las respuestas

#41 Penta
05/05/2008 - 22:53 | Informe spam
Hola
Pues ami la primera sesion se me quedo pegada.
La segunda registro las transacciones de 1 a 1002 pero en el campo ID
se salto el Nº 2

Atte.
Penta.
Respuesta Responder a este mensaje
#42 Alfredo Novoa
05/05/2008 - 22:54 | Informe spam
El Mon, 5 May 2008 13:40:03 -0700, Gux (MVP) escribió:

SERIALIZABLE no es suficiente.

El script que ofreció Alejandro, con isolation SERIALIZABLE provoca
deadlocks. La alternativa que pude hacer funcionar es la que muestro en otro
post, donde aplico un hint TABLOCK cuando calculo el MAX.



Me ha parecido entender leyendo por ahí que por defecto los selects no
bloquean nada :-(

SERIALIZABLE si debería de ser suficiente.


Saludos
Respuesta Responder a este mensaje
#43 Carlos M. Calvelo
05/05/2008 - 23:03 | Informe spam
Hola Gux,

On 5 mei, 22:40, Gux (MVP) wrote:
SERIALIZABLE no es suficiente.




Si inicialmente hago una inserción de un registro, y después dos
transacciones distintas, cada una introducen 1000 registros,
espero 2001 registros.

Con READ COMMITTED las dos trasacciones dicen haber ejecutado bien,
pero no tengo 2001 registros. Eso no es correcto.

Con SERIALIZABLE una de las transacciones rompe y la otra ejecuta
bien. Espero entonces 1001 registros. Y los tengo.
Este es comportamiento correcto.

El script que ofreció Alejandro, con isolation SERIALIZABLE provoca
deadlocks.



Y como debe ser una de las transacciones pierde la partida.
Comportamiento correcto.


La alternativa que pude hacer funcionar es la que muestro en otro
post, donde aplico un hint TABLOCK cuando calculo el MAX.




Esa no la he probado todavía.

Saludos,
Carlos
Respuesta Responder a este mensaje
#44 Alejandro Mesa
05/05/2008 - 23:04 | Informe spam
Gux,

1 - Con cual version lo probastes?

INSERT INTO dbo.t1 (contador, [id])
VALUES ('contador 1', (SELECT MAX(id) + 1
FROM dbo.t1 WITH (TABLOCK)
WHERE contador = 'contador 1'))



Msg 1046, Level 15, State 1, Line 2
Subqueries are not allowed in this context. Only scalar expressions are
allowed.

2 - Si usamos el lock hint TABLELOCK, entonces no necesitamos subir el nivel
de la transaccion. Ese hint hace que se adquiera un lock tipo SIX que no es
compatible con S ni U y por lo tanto toda transaccion de lectura en esa tabla
tendra que esperar.

Si trabaja como se espera, pero a cual precio.

Deja ver si maniana podemos seguir el tema.

AMB


"Gux (MVP)" wrote:

De la siguiente manera ejecutó correctamente sin violaciones de PK ni
deadlocks:


USE tempdb
GO

DECLARE @i INT

SET @i = 1

WAITFOR TIME '16:26:00'

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE

WHILE @i <= 1000
BEGIN
BEGIN TRANSACTION

INSERT INTO dbo.t1 (contador, [id])
VALUES ('contador 1', (SELECT MAX(id) + 1
FROM dbo.t1 WITH (TABLOCK)
WHERE contador = 'contador 1'))

COMMIT TRANSACTION

SET @i = @i + 1
END

SET TRANSACTION ISOLATION LEVEL READ COMMITTED
GO




USE tempdb
GO

DECLARE @i INT

SET @i = 1

WAITFOR TIME '16:26:00'

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE

WHILE @i <= 1000
BEGIN
BEGIN TRANSACTION

INSERT INTO dbo.t1 (contador, [id])
VALUES ('contador 1', (SELECT MAX(id) + 1
FROM dbo.t1 WITH (TABLOCK)
WHERE contador = 'contador 1'))

COMMIT TRANSACTION

SET @i = @i + 1
END

SET TRANSACTION ISOLATION LEVEL READ COMMITTED
GO


Gustavo Larriera, Microsoft MVP
https://mvp.support.microsoft.com/p...o.larriera
Este mensaje se proporciona tal como es, sin garantías de ninguna clase.



"Alejandro Mesa" wrote:

> Gux,
>
> Te lo dejo de prueba, veras lo que pasa cuando usas SERIALIZABLE .
>
>
> AMB
>
> "Gux (MVP)" wrote:
>
> > Gracias por el código Alejandro. Intentaré probarlo en cuanto esté en una
> > máquina con SQL instalado.
> >
> > Seré curioso, antes de probar tu código: El isolation level no debería ser
> > SERIALIZABLE ?
> >
> > Gustavo Larriera, Microsoft MVP
> > https://mvp.support.microsoft.com/p...o.larriera
> > Este mensaje se proporciona tal como es, sin garantías de ninguna clase.
> >
> >
> >
> > "Alejandro Mesa" wrote:
> >
> > > Hola Gustavo,
> > >
> > > Que tal si probamos con codigo.
> > >
> > > Sesion 1:
> > >
> > > use tempdb
> > > go
> > >
> > > DROP TABLE dbo.t1
> > > GO
> > >
> > > CREATE TABLE dbo.t1 (
> > > transaccion_id INT NOT NULL IDENTITY PRIMARY KEY,
> > > dt DATETIME NOT NULL DEFAULT(GETDATE()),
> > > contador VARCHAR(25) NOT NULL,
> > > [id] INT NOT NULL,
> > > CONSTRAINT UQ_transaccion_contador_id UNIQUE (contador, id)
> > > )
> > > GO
> > >
> > > INSERT INTO dbo.t1 (contador, id) VALUES('contador 1', 1)
> > > GO
> > >
> > > Antes de ejecutar esta parte, favor usar un tiempo no lejano en el futuro
> > > para que ambas sesiones ejecuten este codigo al mismo tiempo.
> > >
> > > DECLARE @i INT
> > >
> > > SET @i = 1
> > >
> > > WAITFOR TIME '13:15:00'
> > >
> > > SET TRANSACTION ISOLATION LEVEL READ COMMITTED
> > >
> > > WHILE @i <= 1000
> > > BEGIN
> > > BEGIN TRANSACTION
> > >
> > > INSERT INTO dbo.t1 (
> > > contador,
> > > [id]
> > > )
> > > SELECT 'contador 1', MAX(id) + 1
> > > FROM dbo.t1 AS c
> > > WHERE contador = 'contador 1'
> > >
> > > COMMIT TRANSACTION
> > >
> > > SET @i = @i + 1
> > > END
> > >
> > > SET TRANSACTION ISOLATION LEVEL READ COMMITTED
> > > GO
> > >
> > > Session 2
> > >
> > > use tempdb
> > > go
> > >
> > > DECLARE @i INT
> > >
> > > SET @i = 1
> > >
> > > WAITFOR TIME '13:15:00'
> > >
> > > SET TRANSACTION ISOLATION LEVEL READ COMMITTED
> > >
> > > WHILE @i <= 1000
> > > BEGIN
> > > BEGIN TRANSACTION
> > >
> > > INSERT INTO dbo.t1 (
> > > contador,
> > > [id]
> > > )
> > > SELECT 'contador 1', MAX(id) + 1
> > > FROM dbo.t1 AS c
> > > WHERE contador = 'contador 1'
> > >
> > > COMMIT TRANSACTION
> > >
> > > SET @i = @i + 1
> > > END
> > >
> > > SET TRANSACTION ISOLATION LEVEL READ COMMITTED
> > > GO
> > >
> > > Si creen que el nivel READ COMMITTED no es suficiente, entonces cambienlo en
> > > ambas sessiones y vean los resultados.
> > >
> > >
> > > AMB
> > >
> > > "Gux (MVP)" wrote:
> > >
> > > > "Alfredo Novoa" wrote:
> > > >
> > > > > wrote:
> > > > >
> > > > > >Hola Antonio, a mi me parece correcto usar la tabla numeradora y los
> > > > > >bloqueos, a la larga es lo mas eficiente que podes hacer y seguro. Si haces
> > > > > >un Max sobre la tabla y esta tiene millones de registros no va a ser tan
> > > > > >rapido como hacer un update sobre la tabla numeradora de unos pocos
> > > > > >registros.
> > > > >
> > > > > ¿Por que?
> > > > >
> > > > > Para eso están los índices.
> > > >
> > > > Exacto.
> > > >
> > > > Si hay una consulta que usa funciones agregadas (mi libre traducción de
> > > > "aggregate" :-)) considerar el uso de un índice no-clustered. Estos índices
> > > > incluyen una fila con el valor de índice para cálculos agregados, por lo que
> > > > SQL Server no necesita acceder a la tabla real para hacer el cálculo de la
> > > > función.
> > > >
> > > >
> > > > Gustavo Larriera, Microsoft MVP
> > > > https://mvp.support.microsoft.com/p...o.larriera
> > > > Este mensaje se proporciona tal como es, sin garantías de ninguna clase.
> > > >
> > > >
> > > >
> > > > "Alfredo Novoa" wrote:
> > > >
> > > > >
> > > > > Hola Maxi,
> > > > >
> > > > > On Mon, 5 May 2008 10:53:28 -0300, "Maxi"
> > > > > wrote:
> > > > >
> > > > > >Hola Antonio, a mi me parece correcto usar la tabla numeradora y los
> > > > > >bloqueos, a la larga es lo mas eficiente que podes hacer y seguro. Si haces
> > > > > >un Max sobre la tabla y esta tiene millones de registros no va a ser tan
> > > > > >rapido como hacer un update sobre la tabla numeradora de unos pocos
> > > > > >registros.
> > > > >
> > > > > ¿Por que?
> > > > >
> > > > > Para eso están los índices.
> > > > >
> > > > > >aplicaciones por el costo a nivel performance que tiene eso, ademas de que
> > > > > >estarias haciendo un select y si dos hacen el mismo Max y no consideras
> > > > > >otras cosas a nivel bloqueo podria darles el mismo numero)
> > > > >
> > > > > ¿Que más habría que considerar?
> > > > >
> > > > >
> > > > >
> > > > > Saludos
> > > > >
Respuesta Responder a este mensaje
#45 Gux (MVP)
05/05/2008 - 23:06 | Informe spam
"Alfredo Novoa" wrote:

El Mon, 5 May 2008 12:30:00 -0700, Gux (MVP) escribió:

> De la siguiente manera ejecutó correctamente sin violaciones de PK ni
> deadlocks:

>SET TRANSACTION ISOLATION LEVEL SERIALIZABLE

> INSERT INTO dbo.t1 (contador, [id])
> VALUES ('contador 1', (SELECT MAX(id) + 1
> FROM dbo.t1 WITH (TABLOCK)
> WHERE contador = 'contador 1'))

Gracias Gux, no conocía este truquillo. ¿No funcionaría poniendo WITH
ROWLOCK?




Me temo que el hint ROWLOCK en el SELECT MAX no va a servir pues lo que yo
quiero es bloquear todo el conjunto de filas afectadas.

De todas formas parece que aun no tienen muy logrado lo de la concurrencia.




Veamos: Administro un base de datos de una aplicación con 25 mil usuarios
concurrentes y todo anda de maravillas. Pero también sé de una aplicación de
unas decenas de usuarios que, en el mismo servidor, tienen mucho bloqueo y
hasta deadlocks.

En resumen: Las aplicaciones concurrentes funcionan tan bien según hayan
sido bien programadas. SQL Server no es más que una mascota que hace los
trucos que se le han enseñado :-)

Una duda: ¿No debería de llegar con poner REPEATABLEREAD?



No lo he probado en mi ejemplo.



Saludos
Alfredo




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