MSSQL Server REPEATABLE READ Isolation Level

REPEATABLE READ (Tekrarlanabilir Okuma), MSSQL Server’da tutarlılık ve performans arasında bir denge kuran izolasyon seviyesidir. Temel mantığı şudur: Bir işlem (transaction) içinde bir satırı okuduğunuzda, işlem bitene kadar o satırın değişmeyeceği garanti edilir. Kirli okumayı (dirty read) engeller:  Başka bir transaction, henüz commit edilmemiş değişiklikleri göremez.  Tekrar eden okuma hatasını (non-repeatable read) engeller: Aynı transaction içinde aynı veriyi iki kez okursan, başka bir transaction bu veriyi değiştiremez veya silemez. Yani, siz veriyi bir kez okuduğunuzda, siz “işim bitti” diyene kadar başka hiç kimse o veriyi değiştiremez. Ancak phantom read olabilir: Başka bir transaction yeni bir kayıt ekleyebilir ve bu transaction sona erdiğinde, tekrar yapılan sorgularda yeni kayıtlar görünebilir.

Bu seviyede SQL Server, sorgu tarafından okunan tüm veriler üzerine Paylaşımlı (Shared – S) kilitler koyar. Varsayılan seviye olan READ COMMITTED’dan farkı şudur:

  •  READ COMMITTED: Kilidi satırı okur okumaz bırakır.
  •  REPEATABLE READ: Kilidi işlem (transaction) tamamlanana veya geri alınana kadar tutmaya devam eder.

Hangi işlemi engellemekte veya hangi işleme izin vermektedir.

  • Kirli Okumalar (Dirty Reads): Başka bir işlemin henüz onaylamadığı (commit etmediği) verileri okuyamazsınız.
  •  Tekrarlanamayan Okumalar (Non-Repeatable Reads): Bir satırı okuduktan sonra, siz işleminizi bitirmeden başka biri o satırı güncelleyemez veya silemez.
  • Phantom Reads – Hayalet Okumalar: Bu seviye mevcut satırları kilitler ancak satırların arasındaki “boşlukları” kilitlemez. Bu nedenle, başka bir kullanıcı sizin sorgu kriterlerinize uyan yeni satırlar ekleyebilir (INSERT). Aynı sorguyu tekrar çalıştırdığınızda, daha önce orada olmayan yeni satırlar görebilirsiniz.

Oturum bazlı aktif etmek için:

SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;

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

Transaction 1:  Belirtilen isolation seviyesinde okuma işlemi yapılması gerekmektedir.

SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN TRANSACTION
SELECT * FROM Musteriler 
-- 30 saniye boyunca bekleyelim (bu sırada başka işlem denensin)
WAITFOR DELAY '00:00:30';
SELECT  *FROM Musteriler 
COMMIT;

COMMIT işlemi bittikten sonra  dönen sonuç aşağıdaki görülmektedir. Neden farklı değerler döndü şimdi bunları inceleyelim. Yukarıdaki sonuç çalıştırıldıktan sonra Transaction 1-2-3 aynı çalıştırılmış oldu.

Aşağıdaki işlemleri yaparken Transaction 1 işlemimiz devam ediyor.
Transaction 2: Ahmet’in bakiyesini değiştirmeye çalışalım. Yukarıdaki commit işleminin gerçekleşmesini bekler. Commit Transaction 1’de gerçekleştikten sonra  update işlemimiz yapılmaktadır.

UPDATE Musteriler SET Bakiye = 20000 WHERE MusteriID = 1;

Transaction 1’de commit ifadesi gerçekleştikten sonra update işlemi gerçekleşir. Yapı gereği beklemektedir.

Sonucumuz yukarıda ilk resimde görüldüğü gibi güncel değil, tekrardan select çektiğimde değerimiz güncellenmiş olacaktır. Select ifademiz sonuçlandıktan sonra update işlemi gerçekleşmiş oldu.

Transaction 2, Transaction 1 bitene kadar güncelleme yapamaz. Fakat yeni müşteri eklenirse Transaction 1 bunu görebilir. 

Yukarıdaki REPEATABLE READ isolation level seviyesi devam ederken insert işlemi gerçekleşmiş oldu.

Transaction 3

insert into Musteriler(Ad,Bakiye)values('Talat',4000)
insert into Musteriler(Ad,Bakiye)values('Kadir',10000)

Yukarıda dikkat edersek aynı anda Transaction 1 işlemi devam ederken select ifadesinde insert ettiğimiz sonuçları görüyoruz. Ayrıca Transaction 1’de commit olmadan önceki select ifadesinde bir insert değerinin geldiği görülmektedir. Update işlemi select sonuçlarım döndükten sonra gerçekleşti. Tabloya ekstra bir select çektiğimde görmüş oldum. Repeatable read yapısında commit işlemi gerçekleşmeden diğer kullanıcılar select çekebilir. Shared lock birbirlerini engellemez. Çünkü transaction1 işlemi select işlemleri shared lock birbirini engellemez.

Yukarıdaki transaction 1 ifadesi içinde olan update delete gibi ifade ise select sonucumuz dönmez.

REPEATABLE READ Phantom Read’leri Önler mi?
Hayalet okuma (phantom read) durumu, transaction içinde belirli bir koşula göre kayıt okunduğunda, başka bir transaction’ın yeni kayıt eklemesiyle ortaya çıkar. Transaction içinde ilk select sorgusunda olmayan bazı yeni satırlar, ikinci select’te görünebilir. Phantom Read önlenmez.

REPEATABLE READ Dirty Read’i Önler mi? Aynı transaction içinde, başka bir transaction’ın commit etmediği veriyi okuyamazsın.

Non-REPEATABLE READ Dirty Read’i Önler mi? Transaction sırasında okuduğun bir satırın başkası tarafından değiştirilmesini engeller. Yani select ettiğin satır bir daha select ettiğinde aynı kalır.

REPEATABLE READ, kilitleri uzun süre tuttuğu için Deadlock riskini önemli ölçüde artırır. Eğer iki farklı işlem aynı veriyi okur (S-Lock) ve sonra her ikisi de aynı anda o veriyi güncellemeye çalışırsa (X-Lock istemi), birbirlerini sonsuza kadar bekletebilirler.

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

dbcc useroptions

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

Kötülüğe iyilikle karşılık verin.Fussilet-34

Author: Yunus YÜCEL

Bir yanıt yazın

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