Justin Grant'in cevabı LOCK_ESCALATION
genel olarak ayarların ne yaptığını açıklıyor , ancak önemli bir ayrıntıyı kaçırıyor ve SSMS'nin onu ayarlayan kodu neden oluşturduğunu açıklamıyor. Özellikle, LOCK_ESCALATION
senaryoda son bir ifade olarak ayarlanması çok garip görünüyor .
Birkaç test yaptım ve işte burada ne olduğuna dair anlayışım.
Kısa versiyon
ALTER TABLE
Ekler açıklamada, bir sütun örtülü bir şema ile ilgisi yoktur masa, üzerinde (SCH-M) kilit değiştirme alır damlalar veya değiştiren LOCK_ESCALATION
bir tablo ayarı. LOCK_ESCALATION
DML ifadeleri (esnasında davranış kilitleme etkiler INSERT
, UPDATE
, DELETE
olup DDL deyimleri sırasında, vb) ( ALTER
). SCH-M kilidi her zaman tüm veritabanı nesnesinin, bu örnekte yer alan bir tablodur.
Bu muhtemelen karışıklığın geldiği yerdir.
SSMS, ALTER TABLE <TableName> SET (LOCK_ESCALATION = ...)
ifadeyi gerekli olmasa bile her durumda komut dosyasına ekler . Bu ifadenin gerekli olduğu durumlarda , o komut dosyasında gerçekleşen tablo şemasındaki değişiklik sırasında tabloyu belirli bir şekilde kilitlememek için tablonun geçerli ayarını korumak eklenir .
Başka bir deyişle, masa olduğu ilk on SCH-M kilit ile kilitlenir ALTER TABLE ALTER COLUMN
tablo şemasını değiştirme tüm çalışma yapılırken açıklamada. Son ALTER TABLE SET LOCK_ESCALATION
ifade bunu etkilemez. O (sadece gelecek DML ifadeleri etkiler INSERT
, UPDATE
, DELETE
bu tablo için, vs.).
İlk bakışta SET LOCK_ESCALATION = TABLE
, tüm tabloyu değiştirdiğimiz (burada şemasını değiştiriyoruz) gerçeğiyle ilgisi var gibi görünüyor , ancak yanıltıcı.
Uzun versiyon
Bazı durumlarda tabloyu değiştirirken SSMS, tüm tabloyu yeniden oluşturan bir komut dosyası oluşturur ve bazı basit durumlarda (sütun ekleme veya bırakma gibi) komut dosyası tabloyu yeniden oluşturmaz.
Bu örnek tabloyu örnek olarak ele alalım:
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
Her tablonun varsayılan LOCK_ESCALATION
olarak ayarlanmış bir ayarı vardır TABLE
. Burada değiştirelim:
ALTER TABLE dbo.Test SET (LOCK_ESCALATION = DISABLE)
Şimdi, Col1
SSMS tablo tasarımcısında türü değiştirmeye çalışırsam , SSMS tüm tabloyu yeniden oluşturan bir komut dosyası oluşturur:
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
Yukarıda LOCK_ESCALATION
, yeni oluşturulan tablo için ayarlandığını görebilirsiniz . SSMS bunu tablonun geçerli ayarını korumak için yapar. SSMS bu satırı, ayarın geçerli değeri varsayılan TABLE
değer olsa bile oluşturur . Sadece güvenli ve açık olmak ve gelecekte bu varsayılan değişiklikler olursa gelecekteki olası sorunları önlemek için, sanırım. Bu mantıklı.
Bu örnekte, SET LOCK_ESCALATION
ifadenin oluşturulması gerçekten gereklidir , çünkü tablo yeniden oluşturulur ve ayarının korunması gerekir.
Yeni bir sütun eklemek gibi SSMS tablo tasarımcısını kullanarak tabloya basit bir değişiklik yapmaya çalışırsam, SSMS tabloyu yeniden oluşturmayan bir komut dosyası oluşturur:
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
Gördüğünüz gibi ALTER TABLE SET LOCK_ESCALATION
, bu durumda hiç gerekli olmasa da , ifadeyi hala ekliyor . Birincisi ALTER TABLE ... ADD
mevcut ayarı değiştirmez. Sanırım, SSMS geliştiricileri, bu ALTER TABLE SET LOCK_ESCALATION
ifadenin hangi durumlarda gereksiz olduğunu belirlemeye ve her zaman, sadece güvenli olmak için üretmeye çalışmak için çaba göstermeye değmeyeceğine karar verdiler . Bu ifadeyi her seferinde eklemenin bir zararı yoktur.
Bir kez daha, LOCK_ESCALATION
tablo şeması ALTER TABLE
deyim yoluyla değişirken, tablo genelindeki ayar önemsizdir . LOCK_ESCALATION
ayarı yalnızca DML ifadelerinin kilitleme davranışını etkiler UPDATE
.
Sonunda, bir alıntı ALTER TABLE
, benim vurgulamak:
ALTER TABLE'da belirtilen değişiklikler hemen uygulanır. Değişiklikler tablodaki satırlarda değişiklik yapılmasını gerektiriyorsa, ALTER TABLE satırları günceller. ALTER TABLE, değişiklik sırasında tablo için meta verilere bile başka hiçbir bağlantının başvurmadığından emin olmak için tablodaki bir şema değiştirme (SCH-M) kilidi alır, sonunda çok kısa bir SCH-M kilidi gerektiren çevrimiçi dizin işlemleri hariç. ALTER TABLE… SWITCH işleminde, kilit hem kaynak hem de hedef tablolarda alınır. Tabloda yapılan değişiklikler günlüğe kaydedilir ve tamamen kurtarılabilir. Bir sütunu bırakmak veya SQL Server'ın bazı sürümlerinde, varsayılan değere sahip bir NOT NULL sütun eklemek gibi çok büyük tablolardaki tüm satırları etkileyen değişikliklerin tamamlanması ve birçok günlük kaydı oluşturulması uzun sürebilir. Bu ALTER TABLE ifadeleri, birçok satırı etkileyen herhangi bir INSERT, UPDATE veya DELETE ifadesiyle aynı özenle yürütülmelidir.