---
title: 'Yalıtım Düzeyleri'
source: 'https://academia.sh/tr/kurslar/ileri-sql/yalitim-duzeyleri'
course: 'İleri SQL'
language: tr
updated: '2026-08-17T18:08:55+00:00'
license: 'CC BY-SA 4.0'
---

# Yalıtım Düzeyleri

Kirli okuma, tekrarlanamayan okuma ve hayalet satır anomalileri, standartta tanımlı dört yalıtım düzeyi, iki bağlantıyla gerçek bir gözlem ve gösterilemeyen düzeyin model üzerinden anlatımı.

Önceki iki ders boyunca veritabanına yalnız bir bağlantı erişiyordu. İşlem kendi
değişikliklerini görüyor, dışarıda bir şey olmuyordu. Gerçek sistemlerde ise aynı anda
birçok bağlantı okur ve yazar; o zaman iki soru anlam kazanır: bir işlem, başka bir işlemin
henüz kesinleştirmediği değişikliği görebilir mi? Aynı sorgu bir işlem içinde iki kez
çalıştırılırsa aynı sonucu verir mi?

**Yalıtım (isolation)**, bu soruların yanıtını belirleyen özelliktir. İlişkisel Kuram
kursundaki ACID sıralamasının üçüncü harfi budur. Tam yalıtım, eşzamanlı çalışan işlemlerin
sonucunun, onları sırayla çalıştırmakla aynı olmasını ister. Bu güçlü garanti pahalıdır; bu
yüzden standart, gevşetilmiş düzeyler tanımlar ve her düzeyi **hangi anomaliye izin
verdiğiyle** tarif eder.

## Üç Anomali

Standart üç okuma anomalisi tanımlar. Üçü de "iki işlem araya girdiğinde okunan verinin
bozulması" ile ilgilidir, ancak bozulmanın biçimi farklıdır.

**Kirli okuma (dirty read).** Bir işlem, başka bir işlemin henüz kesinleştirmediği
değişikliği okur. Diğer işlem geri alınırsa, okunan değer hiç var olmamış bir değerdir.

**Tekrarlanamayan okuma (non-repeatable read).** Bir işlem aynı satırı iki kez okur ve
farklı değerler görür; arada başka bir işlem o satırı güncelleyip kesinleştirmiştir.

**Hayalet satır (phantom row).** Bir işlem aynı koşulu iki kez sorgular ve ikincisinde
koşula uyan **yeni satırlar** görür; arada başka bir işlem satır eklemiştir. Tekrarlanamayan
okumadan farkı, değişenin bir satırın değeri değil, kümenin üyeliği olmasıdır.

Ayrım pratikte önemlidir, çünkü satır kilitleriyle önlenebilen ile önlenemeyen buradan
ayrılır: var olan bir satır kilitlenebilir, henüz var olmayan bir satır kilitlenemez.

## Dört Düzey

Standart dört düzey tanımlar. Her düzey, kendinden gevşek olanların önlediklerini de önler:

| Düzey | Kirli okuma | Tekrarlanamayan okuma | Hayalet satır |
|---|---|---|---|
| `READ UNCOMMITTED` | olabilir | olabilir | olabilir |
| `READ COMMITTED` | olamaz | olabilir | olabilir |
| `REPEATABLE READ` | olamaz | olamaz | olabilir |
| `SERIALIZABLE` | olamaz | olamaz | olamaz |

Tabloyu okurken iki nokta gözden kaçmamalıdır.

Birincisi, tablo **izin verilenleri** sıralar, olacakları değil. `READ COMMITTED` düzeyinde
tekrarlanamayan okuma "olabilir"; her zaman olur demek değildir. Bir motor, daha güçlü bir
garanti sunup yine de o düzeyin adını kullanabilir.

İkincisi, düzeyler bir gerçekleştirim değil, bir **sözleşmedir**. Aynı adı taşıyan iki
motor bunu farklı biçimlerde sağlayabilir: biri kilitleme, diğeri çok sürümlü eşzamanlılık
denetimi kullanabilir. Sonuç, yasaklanan anomalilerin ortaya çıkmamasıdır; yol serbesttir.

Düzey, standartta `SET TRANSACTION ISOLATION LEVEL` deyimiyle seçilir. Hangi düzeylerin
gerçekten sunulduğu motora göre değişir: bazı motorlar dördünü de kabul eder ama bir kısmını
daha güçlü bir düzeye eşler, bazıları hiç seçim sunmaz. Aşağıdaki gözlemin yapıldığı motor
ikinci gruptadır — düzey seçimi yoktur, okumalar tutarlı bir görüntü üzerinden yapılır.

## İki Bağlantıyla Gözlem

Aşağıdaki betik aynı veritabanı dosyasına **iki ayrı bağlantı** açar ve araya girmeyi
denetimli biçimde üretir. Önce okuyucu bir işlem açmadan iki kez okur; sonra aynı okumayı
açık bir işlem içinde yapar. Yazar her iki durumda da aynı işi yapar: bir satırı günceller
ve yeni bir açık ödünç kaydı ekler.

```bash
rm -f yalitim.db yalitim.db-wal yalitim.db-shm
cat > yalitim.mjs <<'JS'
import { DatabaseSync } from 'node:sqlite';

const okuyucu = new DatabaseSync('yalitim.db');
const yazar = new DatabaseSync('yalitim.db');

okuyucu.exec('PRAGMA journal_mode = WAL');
yazar.exec(`
  CREATE TABLE odunc(id INTEGER PRIMARY KEY, kitap_id INT, uye_id INT, alis TEXT,
                     iade TEXT);
  INSERT INTO odunc VALUES (1,1,4,'2024-03-01',NULL),(2,3,4,'2024-03-04',NULL),
                           (3,5,7,'2024-03-06',NULL);
`);

const oku = (b) => b.prepare(
  `SELECT (SELECT alis FROM odunc WHERE id = 1) AS kayit1_alis,
          (SELECT COUNT(*) FROM odunc WHERE iade IS NULL) AS acik_kayit`).get();

console.log('— işlem açmadan okuma —');
console.log('1. okuma:', JSON.stringify(oku(okuyucu)));
yazar.exec("UPDATE odunc SET alis = '2024-03-02' WHERE id = 1");
yazar.exec("INSERT INTO odunc VALUES (4,7,4,'2024-03-11',NULL)");
console.log('yazar bir satırı güncelledi, bir satır ekledi, kesinleştirdi');
console.log('2. okuma:', JSON.stringify(oku(okuyucu)));

console.log('— işlem içinde okuma —');
okuyucu.exec('BEGIN');
console.log('1. okuma:', JSON.stringify(oku(okuyucu)));
yazar.exec("UPDATE odunc SET alis = '2024-03-03' WHERE id = 1");
yazar.exec("INSERT INTO odunc VALUES (5,9,7,'2024-03-13',NULL)");
console.log('yazar aynı işi bir kez daha yaptı ve kesinleştirdi');
console.log('2. okuma:', JSON.stringify(oku(okuyucu)));
okuyucu.exec('COMMIT');
console.log('işlem bitti, 3. okuma:', JSON.stringify(oku(okuyucu)));
JS
node yalitim.mjs
rm -f yalitim.db yalitim.db-wal yalitim.db-shm
```

```text
— işlem açmadan okuma —
1. okuma: {"kayit1_alis":"2024-03-01","acik_kayit":3}
yazar bir satırı güncelledi, bir satır ekledi, kesinleştirdi
2. okuma: {"kayit1_alis":"2024-03-02","acik_kayit":4}
— işlem içinde okuma —
1. okuma: {"kayit1_alis":"2024-03-02","acik_kayit":4}
yazar aynı işi bir kez daha yaptı ve kesinleştirdi
2. okuma: {"kayit1_alis":"2024-03-02","acik_kayit":4}
işlem bitti, 3. okuma: {"kayit1_alis":"2024-03-03","acik_kayit":5}
```

Birinci bölümde okuyucu işlem açmadı; her `SELECT` kendi başına bir işlemdi. İki okuma
arasında hem satırın değeri değişti — tekrarlanamayan okumanın tanımı — hem de koşula uyan
satır sayısı arttı — hayalet satırın tanımı. Bu bir hata değildir: iki ayrı işlem arasında
dünyanın değişmesi beklenen şeydir.

İkinci bölümde okuyucu `BEGIN` ile bir işlem açtı. Yazar aynı iki değişikliği yaptı ve
kesinleştirdi, ancak okuyucunun ikinci okuması **hiç değişmedi**: ne değer ne sayım. İşlem
kapandıktan sonra yapılan üçüncü okuma yeni durumu gösterdi. Aradaki fark, işlemin ilk
okumada aldığı tutarlı görüntüyü sonuna kadar koruması, yani anlık görüntü üzerinden okumaya
devam etmesidir.

Gözlem, tablonun ilk üç satırının farkını somutlaştırır. İşlem açmadan okuyan taraf,
`READ COMMITTED` düzeyinin izin verdiği davranışı gösterdi: yalnız kesinleşmiş veriyi gördü,
ama tekrarlanan okumaları farklıydı. İşlem içinde okuyan taraf, `SERIALIZABLE` düzeyinin
okuma tarafındaki davranışını gösterdi: hem tekrarlanamayan okuma hem hayalet satır ortadan
kalktı.

## Gösterilemeyen Düzey

Tablodaki dört düzeyden biri bu motorda gözlenemez. `READ UNCOMMITTED`, kesinleşmemiş
değişikliğin okunmasına izin verir; kullanılan motor bunu hiçbir ayarla sunmaz, çünkü
okumalar zaten kesinleşmiş bir anlık görüntüden yapılır. Kirli okumanın sonucunun ne
olduğunu göstermek için gerçek bir motor çıktısı üretilemez.

Bunun yerine davranış **modellenebilir**. Aşağıdaki betik bir veritabanı değildir; tek bir
kaydın kesinleşmiş ve kesinleşmemiş değerlerini tutan küçük bir zamanlama modelidir. Kirli
okumaya izin veren ve vermeyen iki durumda okuyucunun ne göreceğini karşılaştırır:

```bash
cat > kirli-model.mjs <<'JS'
// Kirli okuma modeli: kesinleşmemiş değeri gören bir motorun davranışını taklit
// eder. Gerçek bir motor çıktısı değildir; amaç sonucun ne olduğunu göstermektir.
const kayit = { rafta: 1, kesinlesmemis: null };

const oku = (kirliOkumaVar) =>
  kirliOkumaVar && kayit.kesinlesmemis !== null ? kayit.kesinlesmemis : kayit.rafta;

const dene = (kirliOkumaVar) => {
  kayit.kesinlesmemis = 0;              // yazar: kitabı ödünç verdi, henüz kesinleşmedi
  const gorulen = oku(kirliOkumaVar);   // okuyucu araya girdi
  kayit.kesinlesmemis = null;           // yazar: işlemi geri aldı
  return { okuyucununGordugu: gorulen, geriAlmaSonrasiGercek: kayit.rafta };
};

console.log('kirli okumaya izin veren düzey    :', JSON.stringify(dene(true)));
console.log('kirli okumaya izin vermeyen düzey :', JSON.stringify(dene(false)));
JS
node kirli-model.mjs
```

```text
kirli okumaya izin veren düzey    : {"okuyucununGordugu":0,"geriAlmaSonrasiGercek":1}
kirli okumaya izin vermeyen düzey : {"okuyucununGordugu":1,"geriAlmaSonrasiGercek":1}
```

Birinci satırda okuyucu kitabı ödünç verilmiş gördü; yazar işlemi geri aldığı için o değer
hiçbir zaman gerçek olmadı. Kirli okumanın kötülüğü budur: eski bir değer değil, **hiç var
olmamış** bir değer okunur. Buna dayanarak verilen bir karar — kitabı rezerve etmemek gibi —
hiçbir gerçek duruma karşılık gelmez.

Bu blok bir model olduğu için, çıktısı bir motorun davranışı hakkında kanıt değildir; yalnız
tanımın sonucunu görünür kılar. Bir motorda `READ UNCOMMITTED` gerçekten sunuluyorsa, aynı
sonucun o motorda ölçülmesi gerekir.

## Düzey Seçmek

Düşük düzeyler daha az koordinasyon, dolayısıyla daha yüksek eşzamanlılık sağlar. Bedeli,
uygulamanın anomalilerle kendi başına baş etmesidir.

Karar, işin okuduğu veriye ne yaptığına bakılarak verilir. Okunan değer yalnız
görüntüleniyorsa gevşek bir düzey yeterlidir; okunan değere dayanarak **yazma** yapılıyorsa
— "rafta mı diye bak, raftaysa ödünç ver" — gevşek düzey sessiz bir hataya kapı açar. İki
işlem aynı anda rafta görüp aynı kitabı iki üyeye verebilir.

Bu duruma **kayıp güncelleme** denir ve yalnız yalıtım düzeyi yükseltilerek değil, okumayı
kilitleyerek de önlenebilir. İki yolun da bedeli, aynı satıra dokunan işlemlerin
birbirini beklemesidir. Sonraki dersin konusu bu bekleme mekanizmasıdır.

## Özet

- Kirli okuma kesinleşmemiş veriyi, tekrarlanamayan okuma değişmiş bir satır değerini,
  hayalet satır koşula uyan yeni satırları görür.
- Standart dört düzeyi hangi anomaliye izin verdikleriyle tanımlar; tablo izin verilenleri
  sıralar, olacakları değil.
- Düzey bir sözleşmedir, gerçekleştirim değil; aynı adı taşıyan iki motor bunu kilitleme ya
  da çok sürümlü denetimle sağlayabilir.
- İki bağlantılı gözlemde işlem açmadan okuyan taraf hem değer hem satır sayısı değişikliğini
  gördü; açık işlem içinde okuyan taraf ilk okumadaki görüntüyü sonuna kadar korudu.
- Okunan değere dayanarak yazma yapılıyorsa gevşek düzey kayıp güncellemeye kapı açar.

## Sonraki Adım

Yalıtım düzeyleri neyin görünüp neyin görünmeyeceğini söyler, ama bunun bedelini
söylemez. İki işlem aynı satıra yazmak istediğinde biri beklemek zorundadır; beklemenin ne
kadar süreceği, neyin kilitlendiğine bağlıdır. İki işlem birbirinin tuttuğu kaynağı
beklerse hiçbiri ilerleyemez. Sonraki ders kilit türlerini, gerçek bir çakışmada motorun
verdiği hatayı ve karşılıklı beklemenin nasıl çözüldüğünü ele alacak.
