Bir Birleştirme ifadesi için kilitleme seçeneklerim nelerdir?


13

Bir MERGEifade gerçekleştiren saklı bir yordam var .

Birleştirme yapılırken varsayılan olarak tüm tabloyu kilitliyor gibi görünüyor.

Ben de başka şeyler yapıyorum bir işlem içinde bu saklı yordamı çağırıyorum ve keşke sadece etkilenen satırları kilitlemek istiyorum.

İpucu denedim ve MERGE INTO myTable WITH (READPAST)daha az kilitli gibi görünüyordu. Ancak ms doc'da, birincil anahtarı bile atlayarak yinelenen anahtarlar ekleyebileceğini belirten bir uyarı vardı.

İşte benim tablo şeması:

CREATE TABLE StudentDetails
(
StudentID INTEGER PRIMARY KEY,
StudentName VARCHAR(15)
)
GO
INSERT INTO StudentDetails
VALUES(1,'WANG')
INSERT INTO StudentDetails
VALUES(2,'JOHNSON')
GO

CREATE TABLE StudentTotalMarks
(
Id INT IDENTITY PRIMARY KEY,
StudentID INTEGER REFERENCES StudentDetails,
StudentMarks INTEGER
)
GO
INSERT INTO StudentTotalMarks
VALUES(1,230)
INSERT INTO StudentTotalMarks
VALUES(2,255)
GO

İşte benim saklı yordam:

CREATE PROCEDURE MergeTest 
    @StudentId int,
    @Mark int
AS  

WITH Params
AS
(
    SELECT @StudentId as StudentId,
        @Mark as Mark
)
    MERGE StudentTotalMarks AS stm
    USING Params p
    ON stm.StudentID = p.StudentId
    WHEN MATCHED AND stm.StudentMarks > 250 THEN DELETE
    WHEN MATCHED THEN UPDATE SET stm.StudentMarks = p.Mark
    WHEN NOT MATCHED THEN
        INSERT(StudentID,StudentMarks)
        VALUES(p.StudentId, p.Mark);
GO

Kilitlemeyi şu şekilde gözlemliyorum:

begin tran
EXEC MergeTest 1, 1

Ve sonra başka bir oturumda:

EXEC MergeTest 2, 2

İkinci oturum, devam etmeden önce ilkinin tamamlanmasını bekler.


1
WITH (READPAST)SQL Server'a diğer oturumlar tarafından kilitlenen satırları atlamasını bildirir. Bunu yapmak istediğinizden emin misiniz? Ayrıca, bu tablodaki kaç satırı değiştiriyorsunuz? Bize tablo şemasını (dizinler dahil) ve MERGEçalıştırdığınız ifadeyi gösterin .
Nick Chammas

@NickChammas yardım için teşekkür ederim, soruyu ayrıntılarla güncelledim. READPAST'ın kötü olacağını hayal ediyorum ...
John Buchanan

Yanıtlar:


12

StudentTotalMarksKayıtları bulmak için sorgu işlemcisine daha verimli bir erişim yolu vermeniz gerekir . Yazıldığı gibi sorgu, tablonun [StudentID] = [@StudentId]her bir satıra kalan yüklemi içeren tam bir taranmasını gerektirir :

Tarama Planı

UDönüşüm kilitlenmelerinin yaygın bir nedenine karşı temel bir savunma olarak okurken motor kilitleri alır (günceller). Bu davranış , ilk yürütme tarafından (özel) bir kilitle Uzaten kilitlenmiş satırda bir kilit elde etmeye çalışırken ikinci yürütme blokları anlamına gelir X.

Aşağıdaki dizin, gereksiz Ukilitleri almaktan kaçınarak daha iyi bir erişim yolu sağlar :

CREATE UNIQUE INDEX uq1 
ON dbo.StudentTotalMarks (StudentID) 
INCLUDE (StudentMarks);

Sorgu planı artık bir arama işlemi içeriyor StudentID = [@StudentId], bu nedenle Ukilitler yalnızca hedef satırlarda isteniyor:

Plan Ara

Endeks değildir gerekli olduğu UNIQUE(gerçi el altında sorunu çözmek için INCLUDEbu sorgu için bir örtü endeksi yapmak için gereklidir).

Yapma ait tablo, aynı zamanda erişim yolu sorunu çözmek (ve görünüşe göre gereksiz kolon çıkarılabildi). Alternatif anahtarları her zaman bir veya kısıtlaması ile zorunlu kılmalısınız (ve anlamsız yedek anahtarları iyi bir neden olmadan eklemekten kaçınmalısınız).StudentIDPRIMARY KEYStudentTotalMarksIdUNIQUEPRIMARY KEY

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.