La respuesta de Justin Grant explica qué LOCK_ESCALATION
hace la configuración en general, pero pierde un detalle importante y no explica por qué SSMS genera el código que lo establece. Especialmente, parece muy extraño que LOCK_ESCALATION
se establezca como una última declaración en el script.
Hice algunas pruebas y aquí está mi comprensión de lo que está sucediendo aquí.
Version corta
La ALTER TABLE
declaración que agrega, elimina o altera una columna implícitamente toma un bloqueo de modificación de esquema (SCH-M) en la tabla, que no tiene nada que ver con la LOCK_ESCALATION
configuración de una tabla. LOCK_ESCALATION
afecta el comportamiento de bloqueo durante las instrucciones DML ( INSERT
, UPDATE
, DELETE
, etc.), no durante las sentencias DDL ( ALTER
). El bloqueo SCH-M siempre es un bloqueo de todo el objeto de la base de datos, tabla en este ejemplo.
Esto es probablemente de donde viene la confusión.
SSMS agrega la ALTER TABLE <TableName> SET (LOCK_ESCALATION = ...)
declaración a su script en todos los casos, incluso cuando no es necesario. En los casos en que se necesita esta declaración, se agrega para preservar la configuración actual de la tabla, no para bloquear la tabla de alguna manera específica durante el cambio en el esquema de la tabla que ocurre en ese script.
En otras palabras, la tabla se bloquea con el bloqueo SCH-M en la primera ALTER TABLE ALTER COLUMN
instrucción mientras se realiza todo el trabajo de cambiar el esquema de la tabla. La última ALTER TABLE SET LOCK_ESCALATION
declaración no lo afecta. Afecta a las declaraciones DML futuro sólo ( INSERT
, UPDATE
, DELETE
, etc.) para esa tabla.
A primera vista, parece que SET LOCK_ESCALATION = TABLE
tiene algo que ver con el hecho de que estamos cambiando toda la tabla (estamos alterando su esquema aquí), pero es engañoso.
Versión larga
Cuando se modifica la tabla en algunos casos, SSMS genera un script que recrea la tabla completa y en algunos casos más simples (como agregar o soltar una columna) el script no vuelve a crear la tabla.
Tomemos esta tabla de muestra como ejemplo:
CREATE TABLE [dbo].[Test](
[ID] [int] NOT NULL,
[Col1] [nvarchar](50) NOT NULL,
[Col2] [int] NOT NULL,
CONSTRAINT [PK_Test] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
Cada tabla tiene una LOCK_ESCALATION
configuración, que está configurada TABLE
de manera predeterminada. Vamos a cambiarlo aquí:
ALTER TABLE dbo.Test SET (LOCK_ESCALATION = DISABLE)
Ahora, si trato de cambiar el Col1
tipo en el diseñador de tablas SSMS, SSMS genera un script que recrea la tabla completa:
BEGIN TRANSACTION
SET QUOTED_IDENTIFIER ON
SET ARITHABORT ON
SET NUMERIC_ROUNDABORT OFF
SET CONCAT_NULL_YIELDS_NULL ON
SET ANSI_NULLS ON
SET ANSI_PADDING ON
SET ANSI_WARNINGS ON
COMMIT
BEGIN TRANSACTION
GO
CREATE TABLE dbo.Tmp_Test
(
ID int NOT NULL,
Col1 nvarchar(10) NOT NULL,
Col2 int NOT NULL
) ON [PRIMARY]
GO
ALTER TABLE dbo.Tmp_Test SET (LOCK_ESCALATION = DISABLE)
GO
IF EXISTS(SELECT * FROM dbo.Test)
EXEC('INSERT INTO dbo.Tmp_Test (ID, Col1, Col2)
SELECT ID, CONVERT(nvarchar(10), Col1), Col2 FROM dbo.Test WITH (HOLDLOCK TABLOCKX)')
GO
DROP TABLE dbo.Test
GO
EXECUTE sp_rename N'dbo.Tmp_Test', N'Test', 'OBJECT'
GO
ALTER TABLE dbo.Test ADD CONSTRAINT
PK_Test PRIMARY KEY CLUSTERED
(
ID
) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
COMMIT
Puede ver arriba que se establece LOCK_ESCALATION
para la tabla recién creada. SSMS lo hace para preservar la configuración actual de la tabla. SSMS genera esta línea, incluso si el valor actual de la configuración es el TABLE
valor predeterminado . Solo para ser seguro y explícito y evitar posibles problemas futuros si en el futuro este valor predeterminado cambia, supongo. Esto tiene sentido.
En este ejemplo, es realmente necesario generar la SET LOCK_ESCALATION
declaración, porque la tabla se crea de nuevo y su configuración debe conservarse.
Si trato de hacer un cambio simple en la tabla usando el diseñador de tablas SSMS, como agregar una nueva columna, entonces SSMS genera un script que no vuelve a crear la tabla:
BEGIN TRANSACTION
SET QUOTED_IDENTIFIER ON
SET ARITHABORT ON
SET NUMERIC_ROUNDABORT OFF
SET CONCAT_NULL_YIELDS_NULL ON
SET ANSI_NULLS ON
SET ANSI_PADDING ON
SET ANSI_WARNINGS ON
COMMIT
BEGIN TRANSACTION
GO
ALTER TABLE dbo.Test ADD
NewCol nchar(10) NULL
GO
ALTER TABLE dbo.Test SET (LOCK_ESCALATION = DISABLE)
GO
COMMIT
Como puede ver, todavía agrega la ALTER TABLE SET LOCK_ESCALATION
declaración, aunque en este caso no es necesaria en absoluto. El primero ALTER TABLE ... ADD
no cambia la configuración actual. Supongo que los desarrolladores de SSMS decidieron que no vale la pena intentar determinar en qué casos estoALTER TABLE SET LOCK_ESCALATION
declaración es redundante y generarla siempre, solo para estar seguros. No hay daño en agregar esta declaración cada vez.
Una vez más, la LOCK_ESCALATION
configuración de toda la tabla es irrelevante, mientras que el esquema de la tabla cambia a través de la ALTER TABLE
instrucción. LOCK_ESCALATION
la configuración solo afecta el comportamiento de bloqueo de las declaraciones DML, comoUPDATE
.
Finalmente, una cita de ALTER TABLE
, enfatiza la mía:
Los cambios especificados en ALTER TABLE se implementan de inmediato. Si los cambios requieren modificaciones de las filas de la tabla, ALTER TABLE actualiza las filas. ALTER TABLE adquiere un bloqueo de modificación de esquema (SCH-M) en la tabla para asegurarse de que ninguna otra conexión haga referencia incluso a los metadatos de la tabla durante el cambio, excepto las operaciones de índice en línea que requieren un bloqueo SCH-M muy corto al final. En una operación ALTER TABLE ... SWITCH, el bloqueo se adquiere en las tablas de origen y destino. Las modificaciones realizadas en la tabla se registran y son completamente recuperables. Los cambios que afectan a todas las filas en tablas muy grandes, como soltar una columna o, en algunas ediciones de SQL Server, agregar una columna NO NULL con un valor predeterminado, pueden tardar mucho tiempo en completarse y generar muchos registros. Estas instrucciones ALTER TABLE deben ejecutarse con el mismo cuidado que cualquier instrucción INSERT, UPDATE o DELETE que afecte a muchas filas.