SQL Server - Bloqueos en Base de Datos

 
Vista:

Bloqueos en Base de Datos

Publicado por Pedro (2 intervenciones) el 06/03/2008 12:35:23
El escenario donde se produce esta situación es la siguiente:

Servidor Windows 2000
SQL Server 2000 con Service pack 4

Se producen interbloqueos entre dos procedimientos (en la franja horaria de
gran actividad de la aplicación, pues en otros horarios los procesos tardan
menos de un segundo) que atacan a la misma tabla. La tabla consta de 34
campos y unos 60000 registros. Posee una primary key (campo1) y los
siguientes índices:

Indice1: campo2, campo3, campo4, campo5
Indice2: campo4, campo5, campo6
Indice3: campo7

Los procedimientos que se bloquean entre sí son:

Procediemiento1:

UPDATE TABLA
SET campo7=NULL, campo6=NULL, campo5='T'
FROM T_CLASIFICACION_BLOQUEO WHERE campo7=@variable
AND campo5='Valor'

Procediemiento2:

Hace una SELECT y luego un UPDATE, en función de ciertas condiciones, el
WHERE cambia ligeramente:

Caso1.

SELECT Campo1, campoX, campoY, …
FROM TABLA WITH(NOLOCK)
WHERE campo2=@variable1
AND campo3=@variable2
AND campoX is not null
AND campoY=@variable3
AND (campoZ<=@variable4
AND campo4='Valor1'
AND (campo5 = 'Valor2' OR (campo5='Valor3' AND campo7=CONVERT(VARCHAR(8),
@variable5)))
OR campoXX=@variable6
OR (campoXX IS NULL AND campoYY ='Valor4'))
ORDER BY campoX, campo1

begin transaction
UPDATE TABLA
SET campo7=CONVERT(VARCHAR(8), @variable5)), campo4='ValorX', campo6
=GETDATE()
FROM M_TABLA_MAESTRO
INNER JOIN TABLA ON M_TABLA_MAESTRO.campoA = TABLA.campoA
WHERE campo2=@variable1
AND campo3=@variable2
AND campoX is not null
AND campoY=@variable3
AND (campoZ<=@variable4
AND campo4='Valor1'
AND (campo5 = 'Valor2' OR (campo5='Valor3' AND campo7=CONVERT(VARCHAR(8),
@variable5)))
OR campoXX=@variable6
OR (campoXX IS NULL AND campoYY ='Valor4'))
AND COD_ESTADO not in ('ValorA','ValorB', 'ValorC')

if @@error<>0
begin
rollback transaction
return
end
else
commit transaction

Caso2. (en el WHERE no aparece el campo campoX)

SELECT Campo1, campoX, campoY, …
FROM TABLA WITH(NOLOCK)
WHERE campo2=@variable1
AND campo3=@variable2
AND campoY=@variable3
AND (campoZ<=@variable4
AND campo4='Valor1'
AND (campo5 = 'Valor2' OR (campo5='Valor3' AND campo7=CONVERT(VARCHAR(8),
@variable5)))
OR campoXX=@variable6
OR (campoXX IS NULL AND campoYY ='Valor4'))
ORDER BY campoX, campo1

begin transaction
UPDATE TABLA
SET campo7=CONVERT(VARCHAR(8), @variable5)), campo4='ValorX', campo6
=GETDATE()
FROM M_TABLA_MAESTRO
INNER JOIN TABLA ON M_TABLA_MAESTRO.campoA = TABLA.campoA
WHERE campo2=@variable1
AND campo3=@variable2
AND campoY=@variable3
AND (campoZ<=@variable4
AND campo4='Valor1'
AND (campo5 = 'Valor2' OR (campo5='Valor3' AND campo7=CONVERT(VARCHAR(8),
@variable5)))
OR campoXX=@variable6
OR (campoXX IS NULL AND campoYY ='Valor4'))
AND COD_ESTADO not in ('ValorA','ValorB', 'ValorC')

if @@error<>0
begin
rollback transaction
return
end
else
commit transaction

Caso 3 (en el WHERE se fuerza al campo campos a un valor determinado)

SELECT Campo1, campoX, campoY, …
FROM TABLA WITH(NOLOCK)
WHERE campo2=@variable1
AND campo3=@variable2
AND campoX =@variableX
AND campoY=@variable3
AND (campoZ<=@variable4
AND campo4='Valor1'
AND (campo5 = 'Valor2' OR (campo5='Valor3' AND campo7=CONVERT(VARCHAR(8),
@variable5)))
OR campoXX=@variable6
OR (campoXX IS NULL AND campoYY ='Valor4'))
ORDER BY campoX, campo1

begin transaction
UPDATE TABLA
SET campo7=CONVERT(VARCHAR(8), @variable5)), campo4='ValorX', campo6
=GETDATE()
FROM M_TABLA_MAESTRO
INNER JOIN TABLA ON M_TABLA_MAESTRO.campoA = TABLA.campoA
WHERE campo2=@variable1
AND campo3=@variable2
AND campoX is not null
AND campoY=@variable3
AND (campoZ<=@variable4
AND campo4='Valor1'
AND (campo5 = 'Valor2' OR (campo5='Valor3' AND campo7=CONVERT(VARCHAR(8),
@variable5)))
OR campoXX=@variable6
OR (campoXX IS NULL AND campoYY ='Valor4'))
AND COD_ESTADO not in ('ValorA','ValorB', 'ValorC')

if @@error<>0
begin
rollback transaction
return
end
else
commit transaction

Los registros que se sacan en las actualizaciones o consultas no llegan casi
nunca a la centena.
¿Cuál seria la mejor manera de optimización para minimizar las colisiones
entre procedimientos?
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder

RE:Bloqueos en Base de Datos

Publicado por Isaias (3308 intervenciones) el 07/03/2008 03:05:16
Pedro

Antes de pensar si quiera en OPTIMIZAR, ¿Ya detecto que proceso esta realizando los INTERBLOQUEOS?

Eso es muy facil, con DBCC OPENTRAN y una vez obtenido el #SPID, ejecuta DBCC INPUTBUFFER (#SPID)
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:Bloqueos en Base de Datos

Publicado por Pedro (2 intervenciones) el 07/03/2008 08:24:53
El/los proceso que bloquea/n estan perfectamente identificados.

Son los que estan puestos en el mensaje anterior, los que produccen el caos en la tabla de la base de datos.

Una cosa a tener en cuenta es que los procesos los lanzan los usuarios desde disntintas oficinas y pueden convivir procesos = pero de distintos usuarios
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:Bloqueos en Base de Datos

Publicado por Isaias (3308 intervenciones) el 08/03/2008 00:30:09
Pedro

Si ha identificado que procesos estan generando dichos bloqueos, corriga de origen, o bien, maneje transacciones explicitas (BEGIN TRAN, COMMIT TRAN, ROLLBACK TRAN)
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar