Die Antwort von Justin Grant erklärt, was die LOCK_ESCALATIONEinstellung im Allgemeinen bewirkt, übersieht jedoch ein wichtiges Detail und erklärt nicht, warum SSMS den Code generiert, der sie festlegt. Insbesondere sieht es sehr seltsam aus, dass das LOCK_ESCALATIONals letzte Anweisung im Skript gesetzt ist.
Ich habe nur wenige Tests durchgeführt und hier ist mein Verständnis dafür, was hier passiert.
Kurzfassung
Die ALTER TABLEAnweisung, die implizit eine Spalte hinzufügt, löscht oder ändert, erfordert eine SCH-M-Sperre (Schema Modify) für die Tabelle, die nichts mit der LOCK_ESCALATIONEinstellung einer Tabelle zu tun hat . LOCK_ESCALATIONwirkt sich das Verhalten während der DML - Anweisungen Sperren ( INSERT, UPDATE, DELETE, etc.), nicht während der DDL - Anweisungen ( ALTER). Die SCH-M-Sperre ist immer eine Sperre des gesamten Datenbankobjekts, in diesem Beispiel der Tabelle.
Dies ist wahrscheinlich, woher die Verwirrung kommt.
SSMS fügt die ALTER TABLE <TableName> SET (LOCK_ESCALATION = ...)Anweisung in allen Fällen zu seinem Skript hinzu , auch wenn sie nicht benötigt wird. In den Fällen , wenn diese Anweisung benötigt wird, wird es hinzugefügt , um die aktuelle Einstellung der Tabelle zu erhalten, nicht um die Tabelle zu sperren in irgendeiner bestimmten Weise während der Änderung der Tabelle Schema , das in diesem Skript passiert.
Mit anderen Worten, die Tabelle wird bei der ersten ALTER TABLE ALTER COLUMNAnweisung mit der SCH-M-Sperre gesperrt, während die gesamte Arbeit zum Ändern des Tabellenschemas erledigt ist. Die letzte ALTER TABLE SET LOCK_ESCALATIONAussage hat keinen Einfluss darauf. Es wirkt sich nur Aussagen über zukünftige DML ( INSERT, UPDATE, DELETE, etc.) für diese Tabelle.
Auf den ersten Blick sieht es so aus, als hätte SET LOCK_ESCALATION = TABLEes etwas damit zu tun, dass wir die gesamte Tabelle ändern (wir ändern hier ihr Schema), aber es ist irreführend.
Lange Version
Wenn Sie die Tabelle in einigen Fällen ändern, generiert SSMS ein Skript, das die gesamte Tabelle neu erstellt, und in einigen einfacheren Fällen (z. B. Hinzufügen oder Löschen einer Spalte) erstellt das Skript die Tabelle nicht neu.
Nehmen wir diese Beispieltabelle als Beispiel:
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
Jede Tabelle verfügt über eine LOCK_ESCALATIONEinstellung, die TABLEstandardmäßig festgelegt ist. Lassen Sie es uns hier ändern:
ALTER TABLE dbo.Test SET (LOCK_ESCALATION = DISABLE)
Wenn ich nun versuche, den Col1Typ im SSMS-Tabellen-Designer zu ändern, generiert SSMS ein Skript, das die gesamte Tabelle neu erstellt:
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
Sie können oben sehen, dass es LOCK_ESCALATIONfür die neu erstellte Tabelle festgelegt wird. SSMS tut dies, um die aktuelle Einstellung der Tabelle beizubehalten. SSMS generiert diese Zeile, auch wenn der aktuelle Wert der Einstellung der Standardwert TABLEist. Nur um sicher und explizit zu sein und mögliche zukünftige Probleme zu vermeiden, wenn sich diese Standardeinstellung in Zukunft ändert, denke ich. Das macht Sinn.
In diesem Beispiel ist es wirklich erforderlich, die SET LOCK_ESCALATIONAnweisung zu generieren , da die Tabelle neu erstellt wird und ihre Einstellung beibehalten werden muss.
Wenn ich versuche, mithilfe des SSMS-Tabellen-Designers eine einfache Änderung an der Tabelle vorzunehmen, z. B. eine neue Spalte hinzuzufügen, generiert SSMS ein Skript, das die Tabelle nicht neu erstellt:
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
Wie Sie sehen können, wird die ALTER TABLE SET LOCK_ESCALATIONAnweisung trotzdem hinzugefügt , obwohl sie in diesem Fall überhaupt nicht benötigt wird. Die erste ALTER TABLE ... ADDändert die aktuelle Einstellung nicht. Ich denke, SSMS-Entwickler haben entschieden, dass es sich nicht lohnt, festzustellen, in welchen Fällen diese ALTER TABLE SET LOCK_ESCALATIONAnweisung redundant ist, und sie immer zu generieren, nur um sicher zu gehen. Es schadet nicht, diese Aussage jedes Mal hinzuzufügen.
Auch hier ist die tabellenweite LOCK_ESCALATIONEinstellung irrelevant, während sich das Tabellenschema über die ALTER TABLEAnweisung ändert . LOCK_ESCALATIONDie Einstellung wirkt sich nur auf das Sperrverhalten von DML-Anweisungen aus, z UPDATE.
Zum Schluss ein Zitat aus ALTER TABLE, betonen Sie meins:
Die in ALTER TABLE angegebenen Änderungen werden sofort implementiert. Wenn die Änderungen Änderungen an den Zeilen in der Tabelle erfordern, aktualisiert ALTER TABLE die Zeilen. ALTER TABLE erhält eine SCH-M-Sperre (Schema Modify) für die Tabelle, um sicherzustellen, dass während der Änderung keine anderen Verbindungen auf die Metadaten für die Tabelle verweisen, mit Ausnahme von Online-Indexoperationen, die am Ende eine sehr kurze SCH-M-Sperre erfordern. Bei einer Operation ALTER TABLE… SWITCH wird die Sperre sowohl für die Quell- als auch für die Zieltabelle erfasst. Die an der Tabelle vorgenommenen Änderungen werden protokolliert und können vollständig wiederhergestellt werden. Änderungen, die sich auf alle Zeilen in sehr großen Tabellen auswirken, z. B. das Löschen einer Spalte oder das Hinzufügen einer NOT NULL-Spalte mit einem Standardwert in einigen Editionen von SQL Server, können lange dauern, bis viele Protokolldatensätze abgeschlossen und generiert sind. Diese ALTER TABLE-Anweisungen sollten mit der gleichen Sorgfalt ausgeführt werden wie alle INSERT-, UPDATE- oder DELETE-Anweisungen, die viele Zeilen betreffen.