MSSQL Server READ COMMITTED Isolation Level

SQL Server’da READ COMMITTED, veritabanı kurulduğunda gelen varsayılan (default) izolasyon seviyesidir. Birçok yazılımcı farkında olmasa da yazdığı sorguların çoğu bu kurallar çerçevesinde çalışır.

Bu seviyeyi anlamanın en kolay yolu şudur: “Sadece kapısı kilitli olmayan (commit edilmiş) veriyi oku.”

READ COMMITTED seviyesinde, bir işlem (Transaction A) bir veriyi güncelliyorsa ancak henüz COMMIT veya ROLLBACK yapmamışsa, başka bir işlem (Transaction B) o veriyi okuyamaz. Okumaya çalışırsa, Transaction A işini bitirene kadar bekletilir (blocklanır).

Bu seviye Dirty Read’i engeller ama aşağıdaki iki duruma karşı koruma sağlamaz:

  • Non-Repeatable Read (Tekrarlanamayan Okuma): Bir transaction içinde aynı veriyi iki kez okursanız, arada başka biri veriyi güncelleyip commit ederse, ikinci okumanızda farklı bir sonuç alırsınız.
  • Phantom Read (Hayalet Okuma): Bir aralıktaki verileri okurken (örn: maaşı 5000’den büyük olanlar), başka biri araya yeni bir kayıt eklerse, ikinci okumanızda yeni bir “hayalet” satır belirebilir.

READ COMMITTED Türleri

SQL Server’da bu seviye iki farklı şekilde davranabilir:

A. Locking Read Committed (Geleneksel)

Okuyucular yazarları, yazarlar da okuyucuları engeller. Eğer bir tablo güncelleniyorsa, o tabloyu sorgulayan herkes beklemek zorunda kalır.

B. Read Committed Snapshot Isolation (RCSI)

Bu, modern uygulamalarda çok tercih edilen bir ayardır. Veritabanı bazında aktif edilir (SET READ_COMMITTED_SNAPSHOT ON).

Burada okuyucular yazarları beklemez. Eğer bir veri o an güncelleniyorsa, SQL Server verinin eski halini (snapshot) tempdb üzerinden okuyucuya sunar. Bu, performansı inanılmaz artırır çünkü “blocking” (kilitlenme) sorunlarını minimize eder.

Oturum bazlı aktif etmek için:

SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

Ö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 Committed Isolation Level seviyesini inceleyelim:

Kısaca tekrardan değinmek gerekirse sadece commit edilmiş verileri okur. Read Uncommitted’tan farklı olarak, transaction içerisinde update edilen data commit olmadan başka bir transaction bu datayı okuyamaz. Bu şekilde dirty read oluşumu engellenmiş olur. Diğer taraftan concurrency ve performans azalmış olacaktır.  Okuma konusunda herhangi bir sıkıntı yoktur.

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: Ahmet’in bakiyesini okumaya çalışıyoruz.

SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
SELECT * FROM Musteriler WHERE MusteriID = 1;

Not: SET TRANSACTION ISOLATION LEVEL READ COMMITTED ifadesi yazılmazsa bile normal select ifademizde Read Committed şeklinde çalışmaktadır. Sql serverda default olan yapıdır.

Sonuç: 
Transaction 2, Transaction 1’in commit edilmemiş verisini okuyamaz. Bloklanır ve bekler. Çünkü shared lock ile exclusive lock uyumsuz çalışmaktadır.

COMMIT edildikten sonra sonucumuzun döndüğünü görmüş oluyoruz

Not: Begin Transaction ifadesi kullanılmazsa sql server update’den sonra default olarak commit eder. Bu yapı karşımıza READ COMMITTED olarak geçmektedir.

Yukarıdaki ifadelerde dikkat ederseniz select cümlesi aynı satıra erişmeye çalışıyor. İlgili satır üzerinde exclusive lock oluşur. Bu ifade kendinde sonra gelen tüm ifadeleri engeller. Dikkat ederseniz sadece ilk satıra lock konulmuş bu yüzden başka bir oturumdan ilk satır dışında bulunan diğer satırlara select çekilirse sonuç dönecektir.

Aşağıdaki komutla default olan isolation level öğrenilir.

dbcc useroptions

Başka makalede görüşmek dileğiyle..

İsraf etmeyin. İsra-26

Author: Yunus YÜCEL

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir