La réponse de Justin Grant explique ce que fait le LOCK_ESCALATIONparamètre en général, mais manque un détail important et n'explique pas pourquoi SSMS génère le code qui le définit. Surtout, il semble très étrange que leLOCK_ESCALATION soit défini comme dernière instruction dans le script.
J'ai fait quelques tests et voici ma compréhension de ce qui se passe ici.
Version courte
L' ALTER TABLEinstruction qui ajoute, supprime ou modifie une colonne prend implicitement un verrou de modification de schéma (SCH-M) sur la table, ce qui n'a rien à voir avec le LOCK_ESCALATIONréglage d'une table.LOCK_ESCALATIONaffecte le comportement de verrouillage dans les déclarations DML ( INSERT, UPDATE, DELETE, etc.), et non pas dans les instructions DDL ( ALTER). Le verrou SCH-M est toujours un verrou de tout l'objet de base de données, tableau dans cet exemple.
C'est probablement de là que vient la confusion.
SSMS ajoute l' ALTER TABLE <TableName> SET (LOCK_ESCALATION = ...)instruction à son script dans tous les cas, même lorsqu'elle n'est pas nécessaire. Dans les cas où cette instruction est nécessaire, elle est ajoutée pour conserver le paramètre actuel de la table, pas pour verrouiller la table d'une manière spécifique lors de la modification du schéma de table qui se produit dans ce script.
En d'autres termes, la table est verrouillée avec le verrou SCH-M sur la première ALTER TABLE ALTER COLUMNinstruction pendant que tout le travail de modification du schéma de table est effectué. La dernière ALTER TABLE SET LOCK_ESCALATIONdéclaration ne l'affecte pas. Cela n'affecte que les futures instructions DML (INSERT , UPDATE,DELETE , etc.) pour cette table.
À première vue, il semble que SET LOCK_ESCALATION = TABLE quelque chose à voir avec le fait que nous changeons toute la table (nous modifions son schéma ici), mais c'est trompeur.
Version longue
Lors de la modification de la table dans certains cas, SSMS génère un script qui recrée la table entière et dans certains cas plus simples (comme l'ajout ou la suppression d'une colonne), le script ne recrée pas la table.
Prenons cet exemple de tableau comme exemple:
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
Chaque table a un LOCK_ESCALATIONparamètre, qui est défini TABLEpar défaut. Changeons-le ici:
ALTER TABLE dbo.Test SET (LOCK_ESCALATION = DISABLE)
Maintenant, si j'essaie de changer le Col1type dans le concepteur de table SSMS, SSMS génère un script qui recrée la table entière:
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
Vous pouvez voir ci-dessus qu'il définit LOCK_ESCALATIONpour la table nouvellement créée. SSMS le fait pour conserver le paramètre actuel de la table. SSMS génère cette ligne, même si la valeur actuelle du paramètre est la TABLEvaleur par défaut . Juste pour être sûr et explicite et éviter d'éventuels problèmes futurs si, à l'avenir, cette valeur par défaut change, je suppose. C'est logique.
Dans cet exemple, il est vraiment nécessaire de générer l' SET LOCK_ESCALATIONinstruction, car la table est créée à nouveau et son paramètre doit être conservé.
Si j'essaie d'apporter une modification simple à la table à l'aide du concepteur de table SSMS, par exemple en ajoutant une nouvelle colonne, SSMS génère un script qui ne recrée pas la table:
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
Comme vous pouvez le voir, il ajoute toujours l' ALTER TABLE SET LOCK_ESCALATIONinstruction, même si dans ce cas, ce n'est pas du tout nécessaire. Le premier ALTER TABLE ... ADDne modifie pas le paramètre actuel. Je suppose que les développeurs SSMS ont décidé qu'il ne valait pas la peine d'essayer de déterminer dans quels cas celaALTER TABLE SET LOCK_ESCALATION déclaration est redondante et de la générer toujours, juste pour être sûr. Il n'y a aucun mal à ajouter cette déclaration à chaque fois.
Une fois de plus, le LOCK_ESCALATIONparamètre à l' échelle de la table n'est pas pertinent alors que le schéma de la table change via l' ALTER TABLEinstruction. LOCK_ESCALATIONparamètre affecte uniquement le comportement de verrouillage des instructions DML, commeUPDATE .
Enfin, une citation de ALTER TABLE, souligne la mienne:
Les modifications spécifiées dans ALTER TABLE sont implémentées immédiatement. Si les modifications nécessitent des modifications des lignes de la table, ALTER TABLE met à jour les lignes. ALTER TABLE acquiert un verrou de modification de schéma (SCH-M) sur la table pour s'assurer qu'aucune autre connexion ne référence même les métadonnées de la table pendant la modification, sauf les opérations d'index en ligne qui nécessitent un verrou SCH-M très court à la fin. Dans une opération ALTER TABLE… SWITCH, le verrou est acquis sur les tables source et cible. Les modifications apportées à la table sont consignées et entièrement récupérables. Les modifications qui affectent toutes les lignes dans des tables très volumineuses, telles que la suppression d'une colonne ou, dans certaines éditions de SQL Server, l'ajout d'une colonne NOT NULL avec une valeur par défaut, peuvent prendre du temps à se terminer et générer de nombreux enregistrements de journal. Ces instructions ALTER TABLE doivent être exécutées avec le même soin que toute instruction INSERT, UPDATE ou DELETE qui affecte de nombreuses lignes.