SQL Server 2008 R2 Kirli okumalar - ne kadar atomik değil?


11

"Kirli" kirli okumaların okunmamış bir izolasyon seviyesinin altına nasıl girebileceğini merak ediyorum . Güncellenmiş ancak henüz tamamlanmamış satırların görünür olduğunu anlıyorum, ancak:

  1. Bir satır kısmen güncellenmiş olarak görünebilir - yani, bazı sütunlar güncellenir ve bazıları güncellenmez mi?
  2. Tek bir sütun kısmen güncellenmiş görünebilir. Örneğin, tamamen güncellenen ve aslında 4000 karakter içerdiğini varsayan bir varchar (4000) sütununuz varsa. Önceki durumdan 2k karakter ve yeni durumundan 2k karakter okuyabilir misiniz? Uzunluğu> 8k olan varchar (max) ne olacak?

Güncelleme: Bazı tartışmalardan sonra, minimum fikir birliği, sütun boyutu> 8KB ise, sütunun kendisinde bile kirli okumaların mümkün olmasıdır.

Yanıtlar:


7

Yorumdan MSDN forum bağlantısını okuduktan sonra DÜZENLENMİŞ , çok ilginç.

Yalıtım düzeyinden bağımsız olarak, iki kullanıcı tek bir sayfayı aynı anda güncelleyemez ve hiçbir kullanıcı kısmen güncellenmiş bir sayfayı okuyamaz. SQL Server'ın Col3'ün bayt 17'de başladığını söyleyen bir sayfayla nasıl başa çıkacağını düşünün. Ancak satırın bu kısmı henüz güncellenmediğinden gerçekten byte 25'te başlar. Bir veritabanının bunu halletmesinin bir yolu yoktur.

Ancak 8k'den büyük satırlar için birden çok sayfa kullanılır ve bu, yarı güncellenmiş bir sütunu mümkün kılar. MSDN bağlantısından kopyalandı (bağlantının kopması durumunda), bu sorguyu bir pencerede başlatın:

if object_id('TestTable') is not null
    drop table TestTable
create table TestTable (txt nvarchar(max) not null)
go
insert into TestTable select replicate(convert(varchar(max),
    char(65+abs(checksum(newid()))%26)),100000)
go 10
update TestTable set txt=replicate(convert(varchar(max),
    char(65+abs(checksum(newid()))%26)),100000)
go 100000

Bu bir tablo oluşturur ve sonra 100.000x aynı karakter dizesiyle günceller. İlk sorgu çalışırken, bu sorguyu başka bir pencerede başlatın:

while 1=1 begin
 if exists (select * from TestTable (nolock) where left(Txt,1) <> right(Txt,1))
    break
end

İkinci sorgu yarı güncellenmiş bir sütun okuduğunda durur. Yani, ilk karakter sonuncudan farklı olduğunda. Hızlı güncellenerek, yarı güncellenmiş sütunları okumanın mümkün olduğunu kanıtlar. nolockİpucunu kaldırırsanız, ikinci sorgu hiçbir zaman tamamlanmaz.

Şaşırtıcı sonuç! Yarı güncellenmiş bir XML sütunu bir (nolock)raporu bozabilir , çünkü XML hatalı biçimlendirilir.


1
Social.msdn.microsoft.com/Forums/en-US/transactsql/thread/… 'a göre bu her zaman doğru değildir , ancak kısmen güncellenen hangi sütun türlerinin hala gizemini koruyor.

@Andomar AFAIK mandalları kısmen güncellenmiş bir sayfanın okunmasını önleyecektir, ancak bir NCI'dan bazı sütun değerleri okundu, ancak CI'den bir sütun almak için bir yer imi araması yaptı. NOLOCKEminim altında NCI sütunları satırın bir sürümünden, ancak CI farklı bir sürümünden bir durum oluşturmak mümkün olacaktır. Ayrıca satır dışı veriler ve lob sayfaları, veri sayfasındaki mandal tarafından korunmaz.
Martin Smith

1
@Martin: Katılıyorum, nolockorijinal sırasını bulamayan kendinden bir katılım gördüm . Ancak, bir alanın veya satırın tek bir okuması tutarlı olmalıdır.
Andomar

1
@Andomar, satırdaki sütunlar birden çok sayfaya yayılmadığı sürece. Bağlantımı görün.

2
Bu gerçekten CW olmalı, çünkü orijinal cevap hiç bir yere yakın değildi, Michael mevcut cevabın özünü sağladı. Soruya yönelik yorumunuz hala düzenlenen cevapla aynı fikirde değil.
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.