MSSQL Server’da Read Uncommitted, izolasyon seviyeleri hiyerarşisinin en alt basamağında yer alır. Bu seviyeyi genellikle “hızlı ama riskli” olarak tanımlayabiliriz.
Temel mantığı şudur: Bir işlem (transaction), başka bir işlemin henüz commit edilmemiş (onaylanmamış) verilerini okuyabilir.
Temel Özellikler
- Dirty Read (Kirli Okuma): En belirgin özelliğidir. Veritabanında o an güncellenen ama henüz kaydedilmeyen verileri görebilirsiniz.
- Kilitlenme Yok (No Locking): Bu seviyede yapılan okuma işlemleri “Shared Lock” (S) talep etmez. Bu da okuma işlemlerinin yazma işlemlerini engellemediği anlamına gelir.
- Performans: En hızlı izolasyon seviyesidir çünkü kilit yönetim yükü (overhead) minimumdur.
Bu seviyeyi kullanırken şu üç veri tutarsızlığıyla karşılaşmanız neredeyse kesindir:
- Dirty Read: A kullanıcısı bir bakiyeyi 100’den 200’e günceller ama henüz işlemi bitirmemiştir. Siz o an 200 olarak okursunuz. Eğer A kullanıcısı işlemini ROLLBACK yaparsa (iptal ederse), sizin elinizde aslında hiç var olmamış bir veri kalır.
- Non-Repeatable Read: Aynı transaction içinde bir veriyi iki kez okuduğunuzda, arada başka bir işlem o veriyi değiştirdiği için farklı sonuçlar alabilirsiniz.
- Phantom Read: Siz bir aralığı sorgularken, araya başka bir işlem yeni satırlar ekleyebilir.
Oturum bazlı aktif etmek için:
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
Yukarıdaki işlemi yapmayıp bir tabloda bu kuralı uygulamak için yaygın olarak kullanılan yöntem WITH (NOLOCK) ifadesidir.
Ne zaman kullanılmalıdır. Veritabanında çok yoğun yazma işlemi varsa ve okuma işlemleriniz sürekli “Lock” (kilit) yiyorsa kullanılabilir. Sistem loglarını okurken verinin o anki durumu kritik kullanılabilir. Verilerin anlık %100 doğruluğu yerine genel eğilimin önemli olduğu büyük veri analizlerinde kullanılmaktadır.
Öncelikle, örnek verilerle bir tablo oluşturalım:
CREATE TABLE Musteriler (
MusteriID INT PRIMARY KEY IDENTITY(1,1),
Ad VARCHAR(50),
Bakiye DECIMAL(10,2)
);
INSERT INTO Musteriler (Ad, Bakiye) VALUES
('Ahmet', 1000),
('Mehmet',2000),
('Yunus', 3000);

Şimdi örnekler üzerinden Read Uncommitted Isolation Level seviyesini inceleyelim:
Senaryo:
Transaction 1: Ahmet’in bakiyesini güncelliyoruz fakat henüz commit yapmıyoruz.
Transaction 2: Aynı anda Ahmet’in bakiyesini okuyoruz.
Transaction 1: Ahmet’in bakiyesini güncelle ama commit yapma
BEGIN TRANSACTION
UPDATE Musteriler SET Bakiye = 5000 WHERE MusteriID = 1;
-- COMMIT yapılmadı!
Transaction 2: Başka bir oturumdan okuma işlemi yapıyoruz. Read uncommitted şeklinde yapmazsak kullanıcı veriye ulaşamaz. Transaction 1 ifadesinin commit edilmesi gerekmektedir. Çünkü sql server default olarak Read committed modunda çalışıyor. Yukarıda update yaptığımız işlem ilgili satır üzerinde exclusive lock oluşturur select çektiğimiz sorgu shared lock alır bu iki lock çeşidi uyumsuz olduğu için select sorgumuz sonuç döndürmez. Aşağıdaki resimde dikkat ederseniz sonuç dönmedi.

Select sorgumuza with(nolock) ifadesi yerleştirilirse kirli okuma yapmaktadır. Bu ifade read uncommitted ifadesine karşılık gelmektedir.

Yukarıda resimde dikkat ederseniz kirli okuma yapmış oldu. Çünkü henüz commit edilmemiş. Aynı zamanda kullanıcı tekrardan select çekmesi halinde kullanıcı farklı bir değer görebilir. Buda non repeatable read ve phantom read okuma oluşmasına sebep olmaktadır.
Kaldığımız yerden devam edelim: With(nolock) ifadesi kullanılmayıp Set transaction isolation… komutu ile de işlemlerimizi gerçekleştirelim. Çünkü ikisi aynı ifadeye denk gelmektedir.
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SELECT * FROM Musteriler WHERE MusteriID = 1;

Herhangi bir sebepten dolayı Transaction 1 işlemi rollback olursa Son kullanıcı işlemin güncellenmediğini görmektedir. Normal select sorgularımızda Read Committed olarak çalışmaktadır. Burada yapılan işlemlerde sanki veri commit edilmeden önceki durumu anlamaya çalışıyoruz.
BEGIN TRANSACTION
UPDATE Musteriler SET Bakiye = 5000 WHERE MusteriID = 1;
-- COMMIT yapılmadı!
ROLLBACK

Sonuç:
Transaction 2 read uncommitted ısolation level veya with(nolock) ile commit edilmemiş yeni bakiye olan 5000’i görebilir! Ancak, Transaction 1 rollback yaparsa, Transaction 2 yanlış veri okumuş olur. Yukarıda aynı yapının olduğunu bahsetmiştik.
BEGIN TRANSACTION
UPDATE Musteriler SET Bakiye = 5000 WHERE MusteriID = 1;
ROLLBACK TRANSACTION
Tekrar tablomuza select çektiğimizde yukarıda kullanıcının yanlış veriyi okuduğunu görebiliyoruz.

Not: Yukarıda örnekte bahsettiğimi gibi sorguların sonuna WITH(NOLOCK) hint’ini koyduğumuz takdirde, sorgularımızda Isolation Level’ı set etmemiş olsak bile Read Uncommitted olarak çalışacaktır.
Kirli okuma (dirty read), tekrar eden okuma hatası (non-repeatable read) ve hayalet okuma (phantom read) ifadelerini bu yapıda görebiliriz. Yukarıdaki örnekte dikkat ederseniz güncellenen 5000 değerinin olmadığı görülmektedir.
Update yapılan satır, belirli bir aralık veya page dışında başka bir transaction üzerinde güncellenen bölüm dışında sorgumuz çalıştığında herhangi bir engelleme ile karşılaşmaz. Çünkü yukarıdaki örneğimizde sadece 1 satır üzerinde güncelleme yapıyor. Diğer satırlar üzerinde herhangi bir arama işlemi yapıldığında sorgu sonucumuz dönmektedir. Çünkü lock row seviyesindedir.

Bu isolation seviyesinde insert işlemlerinde herhangi bir sıkıntıya sebebiyet vermemektedir.
Aşağıdaki komutla default olan isolation level öğrenilir.
dbcc useroptions

Başka makalede görüşmek dileğiyle..
Alçak gönüllü şekilde yürüyün. Furkan-63
