Tenemos un problema con un punto muerto y publiqué este question.Servidor SQL, insertar una fila bloquea la tabla completa
Con un poco de ayuda y mucha búsqueda yo mismo creo que descubrí lo que está pasando. Para resolver los interbloqueos sin controlar la escalada de bloqueo, necesito entender por qué el servidor sql bloquea toda la tabla al insertar una fila.
Aquí es mi instrucción de inserción (con variables cambiado el nombre):
DECLARE
@Type1 INT = 11,
@Type2 INT = NULL,
@Value1 VARCHAR(20) = '0',
@Value2 VARCHAR(20) = '0',
@Value3 VARCHAR(20) = '0',
@Value4 VARCHAR(20) = '0',
@Date1 DATETIME = '2011-11-25',
@Date2 DATETIME = '2011-11-25',
@Value5 NVARCHAR(50) = '',
@Value6 NVARCHAR(50) = '',
@Type3 INT = NULL,
@Value7 VARCHAR(20) = '4',
@Type4 INT = 4,
@Type5 INT = 15153,
@Type6 INT = 3,
@Type7 INT = 31,
@Type8 INT = 5976,
@Type9 INT = 5044,
@Guid1 UNIQUEIDENTIFIER = 'a8293471-3hb4-442b-844f-44t92f17n67s',
@Value8 VARCHAR(200) = '02jfgg55savolhffr1mkjf45',
@value10 INT = 1,
@Option2 BIT = 0,
@Value9 VARCHAR(20) = null,
@Option1 BIT = 0
insert into dbo.OurTable
(
Type1
,Type2
,Value1
,Value2
,Value3
,Value4
,Date1
,Date2
,Value5
,Value6
,Type3
,Value7
,Type4
,Type5
,Type6
,Type7
,Type8
,Type9
,value10
,Col1
,Col2
,Col3
,Col4
,Value8
,Option2
,Value9
)
values
(
CASE
WHEN [dbo].[GetType](@Type1, null) = 6 AND @Option1 = 1 AND [dbo].[GetType](@Type4, 0) <> 1
THEN 7
ELSE [dbo].[GetType](@Type1, null)
END
,[dbo].[GetType](@Type2, null)
,case when @Value1 = 'null' then null else CAST(@Value1 as numeric(18, 6)) end
,case when @Value2 = 'null' then null else CAST(@Value2 as numeric(18, 6)) end
,case when @Value3 = 'null' then null else CAST(@Value3 as numeric(18, 6)) end
,case when @Value4 = 'null' then null else CAST(@Value4 as numeric(18, 6)) end
,[dbo].[GetDate](@Date1, null)
,[dbo].[GetDate](@Date2, null)
,@Value5
,@Value6
,[dbo].[GetType](@Type3, null)
,case when @Value7 = 'null' then null else CAST(@Value7 as numeric(18, 6)) end
,[dbo].[GetType](@Type4, null)
,@Type6
,case when LOWER(@Type7) = 'null' then null else @Type7 end
,@Type5
,@Type9
,@Type8
,@value10
,GETDATE()
,GETDATE()
,[dbo].[GetGuid](@Guid1)
,[dbo].[GetGuid](@Guid1)
,@Value8
,@Option2
,case when @Value9 = 'null' then null else CAST(@Value9 as int) end
)
Si me quedo esta declaración en una transacción y luego volver a consultar sys.dm_tran_locks antes de comprometerse consigo 10233 filas que pertenecen a esa sesión.
SELECT *
FROM sys.dm_tran_locks l
WHERE l.resource_type <> 'DATABASE' AND l.request_session_id = 65
65 es el ID de sesión de mi ventana actual durante la prueba.
También si miro el bloqueo de la mesa (que es la causa de mi punto muerto) puedo ver que pone un candado X en la mesa OurTable.
resource_type resource_associated_entity_id Name resource_lock_partition request_mode request_type request_status
OBJECT 290100074 OurTable 0 X LOCK GRANT
OBJECT 290100074 OurTable 1 X LOCK GRANT
OBJECT 290100074 OurTable 2 X LOCK GRANT
OBJECT 290100074 OurTable 3 X LOCK GRANT
OBJECT 290100074 OurTable 4 X LOCK GRANT
OBJECT 290100074 OurTable 5 X LOCK GRANT
OBJECT 290100074 OurTable 6 X LOCK GRANT
OBJECT 290100074 OurTable 7 X LOCK GRANT
OBJECT 290100074 OurTable 8 X LOCK GRANT
OBJECT 290100074 OurTable 9 X LOCK GRANT
OBJECT 290100074 OurTable 10 X LOCK GRANT
OBJECT 290100074 OurTable 11 X LOCK GRANT
OBJECT 290100074 OurTable 12 X LOCK GRANT
OBJECT 290100074 OurTable 13 X LOCK GRANT
OBJECT 290100074 OurTable 14 X LOCK GRANT
OBJECT 290100074 OurTable 15 X LOCK GRANT
No sé si esto se hace debido a lock escalation o si se solicita un bloqueo exclusivo sobre la mesa desde el principio. De todos modos, esto me causa problemas con los bloqueos.
La razón por la que hay 16 filas de bloqueo en una sola tabla se debe a lock partitioning.
Mi pregunta es, ¿por qué no solicitar un bloqueo exclusivo intención (IX) en la mesa? En cambio, solicita un bloqueo exclusivo. ¿Cómo evito esto? No recibo consejos de ajuste en el afinador, ya lo he intentado.
EDIT Hay un disparador de inserción en OurTable que actualiza un campo en OurTable3. Se ve así:
UPDATE OurTable3 SET Date1 = NULL
FROM OurTable3 as E
JOIN OurTable2 as C on E.Id = C.FKId
JOIN OurTable as ETC on ETC.FKId = C.Id
AND (ETC.Date2 IS NULL OR CAST(ETC.Date2 AS DATE) > E.Date1)
AND ETC.Type1 = 1
Como se puede ver que no se actualiza OurTable pero OurTable consultar con el fin de actualizar la fila correcta en OurTable3.
¿Has mirado el nivel de aislamiento de transacción? http://msdn.microsoft.com/en-us/library/ms173763.aspx – dash
¿Es posible que todas esas funciones hagan referencia a "OurTable" también? Ejecuta MUCHAS funciones allí ... – JNK
¿Cuál es la estructura de la tabla? ¿Tienes una clave de agrupamiento? –