MS SQL Server'da tüm tabloyu kilitlememek için SQL ekleme ve / veya güncelleştirme alma


13

DB çalışmalarında bir acemi, bu yüzden temel bir soru ile sabrınız için teşekkür ederiz. SQL Server 2014'ü yerel makinemde çalıştırıyorum ve farklı yaklaşımları test etmek için küçük bir tablo ve temel istemci uygulaması var. Her ikisi de INSERT INTOve UPDATEdeyimleri sırasında bir tablo kilidi gibi görünen alıyorum . İstemci aşağıdaki kodu içeren bir ASP.NET uygulamasıdır:

OleDbConnection cn = new OleDbConnection("Provider=SQLNCLI11; server=localhost\\SQLEXPRESS; Database=<my db>; user id=<my uid>; password=<my pwd>");
cn.Open();
OleDbTransaction tn = cn.BeginTransaction();
OleDbCommand cmd = new OleDbCommand("INSERT INTO LAYOUTSv2 (LAYOUTS_name_t, LAYOUTS_enabled_b, LAYOUTS_data_m) VALUES ('name', '-1', 'data')", cn, tn);
cmd.ExecuteNonQuery();
cmd.CommandText = "SELECT SCOPE_IDENTITY()";
int newkey = Decimal.ToInt32((decimal)cmd.ExecuteScalar());
Console.WriteLine("Created index " + newkey);
Thread.Sleep(15000);
tn.Commit();
tn = cn.BeginTransaction();
cmd.CommandText = "UDPATE LAYOUTSv2 SET LAYOUTS_enabled_b='-3' WHERE LAYOUTS_key='" + newkey + "'";
cmd.Transaction = tn;
cmd.ExecuteNonQuery();
Console.WriteLine("updated row");
Thread.Sleep(15000);
tn.Rollback();
cn.Close();

Bu kodu çalıştırıyorum, sonra çalıştırdığım yönetim stüdyosundan SELECT * FROM LAYOUTSv2. Her iki durumda da istemci iş parçacığı duraklatıldığında (yani, kesin / geri alma işleminden önce), SELECT sorgusu kesin / geri alma gerçekleşene kadar askıda kalır.

Tabloda birincil anahtar olarak atanmış LAYOUTS_key alanı var. Özellikler penceresinde sayfa kilitleri ve satır kilitlerinin her ikisine de izin verildiği için benzersiz ve kümelenmiş olduğunu gösterir. Tablo için kilit yükseltme ayarı Devre Dışı Bırak ... Tablo ve OTOMATİK diğer kullanılabilir ayarları hiçbir değişiklik yapmadan denedim. Denedim SELECT ... WITH (NOLOCK)ve bu hemen bir sonuç döndürür, ancak burada ve diğer yerlerde iyi uyarıldığı gibi yapmam gereken şey bu değil. ROWLOCKHem INSERTve UPDATEifadeleri ipucu koyarak denedim , ama hiçbir şey değişmedi.

Aradığım davranış şudur: a işleminden önce INSERT, diğer iş parçacıklarından gelen sorgular, düzenlenmekte olan dışındaki tüm satırları okur INSERT. UPDATEDiğer evrelerden bir sorgu yapılmadan önce , düzenlenmekte olan satırın başlangıç ​​sürümünü okuyun UPDATE. Bunu yapmamın bir yolu var mı? Kullanım durumumu açıklığa kavuşturmak için başka bilgiler vermem gerekirse lütfen bize bildirin. Teşekkürler.


3
Bu arada WHERE LAYOUTS_key='" + newkey + "', SQL enjeksiyonu da dahil olmak üzere çeşitli nedenlerle tam bir hayır-hayır, parametreli sorgular kullanmalısınız.
Martin Smith

1
@MartinSmith Bu konudaki başlıklar için teşekkürler ... parametreli sorguları veya SQL Enjeksiyon saldırılarını hiç duymadım.
John Riehl

@JohnRiehl, re: enjeksiyon saldırıları, kullanıcınızın newkey" something';DELETE FROM LAYOUTSv2 --" olarak ayarlanıp ayarlanmadığını hayal edin . Güncellemeniz başarıyla tamamlanır ve ardından kullanıcı kesme işareti ekleyerek sorguyu değiştirdiği için tabloyu boşaltır. Normalde, parametreleştirilmiş bir sorgu benzer görünür UDPATE LAYOUTSv2 SET LAYOUTS_enabled_b='-3' WHERE LAYOUTS_key=?, bundan sonra ?kodunuzdaki (parametreye) değerleri ayrı ayrı atarsınız .
Daniel Hutmacher

Yanıtlar:


10

Muhtemelen "tüm tablo" kilitlemek değil.

Tablodaki bir satırı kilitliyor, ancak SELECT * FROM LAYOUTSv2tüm tabloyu okumaya çalışmanız bu kilit tarafından mutlaka engelleniyor.

Ekleme durumu için yalnızca READPASTkilitli UPDATEsatırı atlamak için ipucu belirtebilirsiniz - ancak bu durum için istediğiniz sonucu vermez (satırın başlangıç ​​sürümünü okumadığında satırı atlar).

Veritabanını okunan anlık görüntü yalıtımı için yapılandırırsanız, bu her iki durum için de istediğiniz etkiyi verir (daha fazla kullanım pahasına tempdb)


"Okunan Taahhütlü Anlık Görüntü Açık mı?" İfadesini True olarak değiştirdim ve şimdi hiçbir ipucu gerekmeden mükemmel çalışıyor. Teşekkürler! Bir takip ... "Anlık Görüntü Yalıtımına İzin Ver" ayarını Yanlış olarak ayarladım ... Tamam mı? Teşekkürler.
John Riehl

@JohnRiehl - Evet, açıkça SNAPSHOTdevre dışı bırakmak için izolasyonu en iyi şekilde kullanmıyorsanız ve daha sonra bunun sizin için yararlı olacağına karar verirseniz etkinleştirin.
Martin Smith

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.