Kilit Yükseltme - Burada neler oluyor?


138

SQL Server 2008'de bir tabloyu değiştirirken (bir sütunu kaldırarak), Değişiklik Komut Dosyası Oluştur düğmesini tıklattım ve oluşturduğu değişiklik komut dosyasının sütunu bıraktığını, "git" dediğini ve ardından ayarlanmış gibi görünen ek bir ALTER TABLE ifadesi çalıştırdığını fark ettim tablonun "TABLE" kilit yükselmesi. Misal:

ALTER TABLE dbo.Contract SET (LOCK_ESCALATION = TABLE)

Ayrıca bu değişiklik komut dosyası yaptığı son şey olduğunu unutmayın. Burada ne yapıyor ve neden LOCK_ESCALATION ayarını TABLE olarak ayarlıyor?

Yanıtlar:


165

" Kilit Yükseltme " SQL'in büyük güncellemeler için kilitlemeyi nasıl ele aldığıdır. SQL çok sayıda satırı değiştirirken, veritabanı motorunun daha küçük şeyleri (ör. Satır kilitleri) kilitlemek yerine daha az, daha büyük kilitler (örneğin tüm tablo) alması daha verimlidir.

Ancak, büyük bir masanız olduğunda bu sorunlu olabilir, çünkü tüm masayı kilitlemek diğer sorguları uzun süre kilitleyebilir. Bu sıra dışıdır: birçok küçük taneli kilit, daha az (veya bir) kaba taneli kilitten daha yavaştır ve bir tablonun farklı bölümlerini kilitleyen birden fazla sorguya sahip olmak, bir işlem diğerini beklerse kilitlenme olasılığını yaratır.

LOCK_ESCALATIONSQL 2008'de yeni, kilit yükseltmenin kontrolüne izin veren tablo düzeyinde bir seçenek vardır . Varsayılan "TABLO" kilitlerin tablo düzeyine kadar yükselmesini sağlar. DEVRE DIŞI BIRAK, çoğu durumda tüm tabloya kilit yükselmesini önler. AUTO, tablo bölümlenmişse tablo kilitlerine izin verir, bu durumda kilitler yalnızca bölüm seviyesine kadar yapılır. Daha fazla bilgi için bu blog yayınına bakın .

TABLE SQL 2008'de TABLE varsayılan olduğundan tablo yeniden oluştururken bu ayarı eklediğinden şüpheleniyorum. LOCK_ESCALATION SQL 2005'te desteklenmediğini unutmayın, bu nedenle komut dosyasını bir 2005 örneği. Ayrıca, TABLO varsayılan olduğundan, komut dosyanızı yeniden çalıştırırken bu satırı güvenle kaldırabilirsiniz.

Ayrıca, bu ayar bulunmadan önce SQL 2005'te, tüm kilitlerin tablo düzeyine yükselebileceğini unutmayın; başka bir deyişle, "TABLE" SQL 2005'teki tek ayardır.



6
@dma_k - CREATE TABLETablo henüz mevcut olmadığından kilitlenecek bir şey olmadığı için bu seçenek alakalı değildir.
Justin Grant

1
Peki neden SSMS'de bir tablo tasarlarken değişiklik komut dosyasındaki ilk ALTER TABLE deyiminden sonra LOCK_ESCALATION deyimi ? Elbette o zamana kadar işler zaten yapıldı. Tablonun yapısını değiştirmeden önce olmamalı mı ?
Ters Mühendis

2
@DaveBoltman - SET, ALTER TABLE ifadesinin bir parçasıdır. Ayrı bir ifade değil. Bkz. Docs.microsoft.com/en-us/sql/t-sql/statements/…
Justin Grant

2
JustinGrant, @DaveBoltman'ın sorusu hala duruyor. SSMS'nin yeni bir sütun eklemek için oluşturduğu komut dosyasının iki ayrı ALTER TABLEifadesi vardır. Önce ALTER TABLE ADD column, sonra GO, sonra ikinci ALTER TABLE SET LOCK_ESCALATION=TABLE, sonra ikinci GO. Böylece, LOCK_ESCALATIONsütun eklendikten sonra ayarlanır. Ondan sonra onu kurmanın anlamı nedir? Bu iki ALTER TABLEifade bir işleme sarılır, ancak sütun LOCK_ESCALATIONayarlanmadan önce eklenir . Sanırım biraz daha kazacağım ve başka bir cevap yazacağım.
Vladimir Baranov

11

Betiğinizin ana bölümünü çalıştırmadan önce ve sonra bu değeri karşılaştırarak betiğinize LOCK_ESCALATION deyimini eklemeniz gerekip gerekmediğini kontrol edebilirsiniz:

SELECT lock_escalation_desc FROM sys.tables WHERE name='yourtablename'

Benim durumumda, bir kısıtlama eklemek veya kısıtlamak için tabloyu değiştirmek bu değeri değiştirmiş gibi görünmüyor.


11

Justin Grant'in cevabı LOCK_ESCALATIONgenel 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_ESCALATIONsenaryoda 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 TABLEEkler 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_ESCALATIONbir tablo ayarı. LOCK_ESCALATIONDML ifadeleri (esnasında davranış kilitleme etkiler INSERT, UPDATE, DELETEolup 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 COLUMNtablo şemasını değiştirme tüm çalışma yapılırken açıklamada. Son ALTER TABLE SET LOCK_ESCALATIONifade bunu etkilemez. O (sadece gelecek DML ifadeleri etkiler INSERT, UPDATE, DELETEbu 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_ESCALATIONolarak ayarlanmış bir ayarı vardır TABLE. Burada değiştirelim:

ALTER TABLE dbo.Test SET (LOCK_ESCALATION = DISABLE)

Şimdi, Col1SSMS 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 TABLEdeğ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_ESCALATIONifadenin 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 ... ADDmevcut ayarı değiştirmez. Sanırım, SSMS geliştiricileri, bu ALTER TABLE SET LOCK_ESCALATIONifadenin 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_ESCALATIONtablo şeması ALTER TABLEdeyim yoluyla değişirken, tablo genelindeki ayar önemsizdir . LOCK_ESCALATIONayarı 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.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.