---
title: 'Okuma ve Yazma İlgileri'
source: 'https://academia.sh/tr/kurslar/nosql/okuma-ve-yazma-ilgileri'
course: 'İlişkisel Olmayan Veri Modelleri'
language: tr
updated: '2026-08-17T18:08:59+00:00'
license: 'CC BY-SA 4.0'
---

# Okuma ve Yazma İlgileri

Onay düzeyinin bir ayar olarak ölçülmesi: aynı ödünç senaryosunun üç yazma ilgisinde koşturulup onay turu, onaylanan yazma ve arıza anında kaybolan yazma sayılarının sayılması, geri alınan yazma ile kayıp yazmanın ayrılması, tüm üyelerden onay istemenin tek bir üye kaybını yazma kesintisine çevirmesinin gösterilmesi ve okuma ilgisi ile okuma yönünün dört bileşiminde yanıtsız istek, bayat okuma ve geri alınacak veriyi gören okuma sayılarının karşılaştırılması.

Önceki iki ders aynı boşluğu bıraktı. Çoğaltma kümesinde kabul edilmiş ödünç kayıtları arıza
sonrasında geri alındı ve bunun nasıl önleneceği söylenmedi; parçalama dersinde her parçanın
kendi çoğaltma kümesi olduğu belirtildi ama bir yazmanın kaç üyeye ulaşmış sayılacağı açıkta
kaldı. Bu iki soru tek bir ayarın iki yüzüdür.

Ayarın adı **yazma ilgisidir** (write concern): bir yazmanın çağırana başarılı diye bildirilmesi
için kaç üyenin onu uygulamış olması gerektiği. Karşılığı okuma tarafında **okuma ilgisidir**
(read concern): bir okumanın hangi doğrulama düzeyiyle yanıtlanacağı. İkisi de derlem ya da
istek başına verilebilen ayarlardır; ne deponun ne de kümenin sabit bir özelliğidir.

## İki Ayrı Ayar

Yazma ilgisinin taşıdığı sayıya **onay düzeyi** denir. `w=1` yalnız birincilin uygulamasını
ister; `w=çoğunluk` üyelerin yarısından fazlasının uygulamasını ister; `w=hepsi` bütün üyeleri
ister. Onay düzeyi yükseldikçe çağıran daha uzun bekler, çünkü onay en yakın üyeden değil, gereken
sayıdaki **en uzak** üyeden döner.

Okuma ilgisinin iki ayarı burada ölçülür. `yerel` okuma, seçilen üyenin elindeki değeri
doğrulamadan döndürür. `çoğunluk` okuması yalnız çoğunluğa ulaşmış — yani geri alınamayacak —
veriyi döndürür. Okuma ilgisinden bağımsız üçüncü bir ayar da vardır ve karıştırılmaması gerekir:
**okuma yönü**, isteğin birinciliye mi bir ikincile mi gideceğini belirler. İkisi ayrı ayrı
seçilir ve ölçümde ayrı sütunlar üretir.

## Düzenek

Aşağıdaki düzenek yine bir **modeldir**: gerçek küme kurulmaz, tur soyut bir adımdır ve üye
uzaklıkları tur cinsinden parametredir. Onay, gereken sayıda üyenin yazmayı uyguladığını
birincilin **öğrenmesidir**; bu yüzden bedeli tek yön değil, gidiş dönüştür.

**NS19 — üyelerin birinciliye uzaklığı 3, 5, 6 ve 8 turdur.** Gerekçe: ikincillerin bir kısmı
aynı binada, bir kısmı uzak bir yerleşkededir. **NS20 — her turda bir ödünç kaydı yazılır ve bir
okuma gelir.** Gerekçe: yazma ile okuma hızının eşit olduğu varsayılır; oran değişirse bayat
okuma sayısı doğrusal olarak değişir. Arıza takvimi birinci dersle aynıdır: birincil durur,
algılama iki tur, seçim iki tur.

```js
// ilgi/model.mjs — onay duzeyi MODELIDIR. Tur soyut bir adimdir; uye basina gecikme, arizanin
// turu ve secim suresi tur cinsinden parametrelerdir, olculmus sure degildir. Gercek kume
// kurulmaz. Yazma her turda bir odunc kaydidir; onay, w uyenin yazmayi uyguladigini birincilin
// ogrenmesidir (gidis-donus, yani gecikmenin iki kati).
export const GECIKME = [0, 3, 5, 6, 8];   // uye basina birincile uzaklik (tur)
export const UYE = 5, ARIZA = 21, ALGILAMA = 2, SECIM = 2, TUR = 48;
const COGUNLUK = Math.floor(UYE / 2) + 1;

export function kosum({ w, okuma = "yerel", yon = "birincil" }) {
  const kapali = new Set();
  const kayit = [0], uygulanan = Array(UYE).fill(0), yazma = [], okunan = [];
  let birincil = 0, sira = 0, bekleme = 0, kesme = null, devir = null;

  // ayaktaki ikincillerin birincile uzakligi, kucukten buyuge
  const uzaklik = () => [...Array(UYE).keys()]
    .filter((i) => i !== birincil && !kapali.has(i))
    .map((i) => Math.abs(GECIKME[i] - GECIKME[birincil])).sort((a, b) => a - b);
  const onaySuresi = (k) => {
    if (k <= 1) return 0;
    const u = uzaklik();
    return u.length >= k - 1 ? 2 * u[k - 2] : null;   // yeterli uye yoksa onay hic gelmez
  };
  // o ana kadar onaylanmis ve geri alinmamis en buyuk sira: bayatligin olculdugu esik
  const sonOnay = (t) => yazma.reduce((m, y) =>
    (y.onay !== null && y.onay <= t && y.geriAlindi === false && y.sira > m ? y.sira : m), 0);

  for (let t = 1; t <= TUR; t += 1) {
    if (t === ARIZA) { kapali.add(birincil); birincil = null; }

    if (birincil === null) {
      bekleme += 1;
      const oy = [...Array(UYE).keys()].filter((i) => !kapali.has(i));
      if (oy.length >= COGUNLUK && bekleme === ALGILAMA + SECIM) {
        birincil = oy.reduce((a, b) => (uygulanan[b] > uygulanan[a] ? b : a));
        kesme = uygulanan[birincil];
        sira = kesme; devir = t;
        for (let x = 0; x < kayit.length; x += 1) kayit[x] = Math.min(kayit[x], kesme);
        for (const y of yazma) if (y.sira > kesme) y.geriAlindi = true;   // gunluk kirpilir
      }
    } else {
      sira += 1;
      kayit[t] = sira;
      const s = onaySuresi(w);
      yazma.push({ sira, gelis: t, onay: s === null ? null : t + s, geriAlindi: false });
      for (let i = 0; i < UYE; i += 1) {
        if (kapali.has(i)) continue;
        uygulanan[i] = i === birincil ? sira
          : Math.max(uygulanan[i], kayit[t - Math.abs(GECIKME[i] - GECIKME[birincil])] ?? 0);
      }
    }
    // birincil olmeden once tamamlanmayan onay hicbir zaman gelmez
    if (t === ARIZA) for (const y of yazma) if (y.onay !== null && y.onay >= t) y.onay = null;

    const ikincil = [...Array(UYE).keys()].filter((i) => i !== birincil && !kapali.has(i));
    const m = yon === "birincil" ? birincil : (ikincil.length ? ikincil[t % ikincil.length] : null);
    if (m === null) { okunan.push({ t, yanitsiz: true }); continue; }  // birincil yokken yanit yok
    const sc = onaySuresi(COGUNLUK);
    const taahhut = sc === null ? sonOnay(t) : Math.min(sonOnay(t), kayit[t - sc] ?? 0);
    const deger = okuma === "yerel" ? uygulanan[m] : Math.min(uygulanan[m], taahhut);
    okunan.push({ t, uye: m, deger, gercek: sonOnay(t), yanitsiz: false });
  }

  const onayli = yazma.filter((y) => y.onay !== null && y.onay <= TUR);
  const yanitli = okunan.filter((o) => o.yanitsiz === false);
  return {
    onayTuru: yazma[0].onay === null ? null : yazma[0].onay - yazma[0].gelis,
    onaylanan: onayli.length, onaysiz: yazma.length - onayli.length,
    geriAlinan: yazma.filter((y) => y.geriAlindi).length,
    kayip: onayli.filter((y) => y.geriAlindi).length,
    sonrasi: onayli.filter((y) => y.gelis > devir).length,
    yanitsiz: okunan.filter((o) => o.yanitsiz).length,
    bayat: yanitli.filter((o) => o.deger < o.gercek).length,
    gerilik: yanitli.reduce((a, o) => a + (o.gercek - o.deger), 0) / yanitli.length,
    // geri alinacak veriyi goren okuma: yalniz ariza oncesi okumalar sayilir, cunku kirpma
    // sonrasi ayni sira numaralari yeniden ve gecerli olarak kullanilir
    hayalet: yanitli.filter((o) => o.t < ARIZA && kesme !== null && o.deger > kesme).length,
    okuma: yanitli.length, devir, kesme,
  };
}
```

```js
// ilgi/olc.mjs — ayni odunc senaryosu uc yazma ilgisinde, sonra dort okuma ayarinda
import { kosum, UYE, ARIZA, TUR, GECIKME } from "./model.mjs";

const s = (x, n) => String(x).padStart(n);
const AD = { 1: "w=1", 3: "w=cogunluk", 5: "w=hepsi" };
console.log(`${UYE} uyeli kume, uye uzakligi ${GECIKME.join("/")} tur. ${TUR} tur, her turda bir`);
console.log(`odunc kaydi. Birincil ${ARIZA}. turda durur; algilama 2, secim 2 tur.\n`);
console.log("yazma ilgisi | onay turu | onaylanan | onaysiz | geri alinan | KAYIP YAZMA | ariza sonrasi onay");
console.log("-------------|-----------|-----------|---------|-------------|-------------|-------------------");
for (const w of [1, 3, 5]) {
  const r = kosum({ w });
  console.log(`${AD[w].padEnd(12)} | ${s(r.onayTuru === null ? "yok" : r.onayTuru, 9)} | ${s(r.onaylanan, 9)} | ` +
    `${s(r.onaysiz, 7)} | ${s(r.geriAlinan, 11)} | ${s(r.kayip, 11)} | ${s(r.sonrasi, 18)}`);
}

console.log("\nokuma tarafi (yazma ilgisi w=1 sabit; kirpma siniri: kayit " + kosum({ w: 1 }).kesme + "):");
console.log("okuma yonu | okuma ilgisi | yanitsiz | bayat okuma | ortalama gerilik | geri alinacak veriyi goren");
console.log("-----------|--------------|----------|-------------|------------------|---------------------------");
for (const yon of ["birincil", "ikincil"]) {
  for (const okuma of ["yerel", "cogunluk"]) {
    const r = kosum({ w: 1, okuma, yon });
    console.log(`${yon.padEnd(10)} | ${okuma.padEnd(12)} | ${s(r.yanitsiz, 8)} | ` +
      `${s(`${r.bayat}/${r.okuma}`, 11)} | ${s(r.gerilik.toFixed(2), 16)} | ${s(r.hayalet, 26)}`);
  }
}

const u = GECIKME.slice(1).sort((a, b) => a - b);
console.log("\nkosumdan bagimsiz: onay turu, ikincillerin uzaklik siralamasindaki (w-1). degerin");
console.log(`iki katidir. Bu kumede siralama ${u.join(" < ")}, yani w buyudukce onay turu`);
console.log(`${u.map((x) => 2 * x).join(", ")} degerlerini alir; hicbir w'de azalmaz.`);
```

```
5 uyeli kume, uye uzakligi 0/3/5/6/8 tur. 48 tur, her turda bir
odunc kaydi. Birincil 21. turda durur; algilama 2, secim 2 tur.

yazma ilgisi | onay turu | onaylanan | onaysiz | geri alinan | KAYIP YAZMA | ariza sonrasi onay
-------------|-----------|-----------|---------|-------------|-------------|-------------------
w=1          |         0 |        44 |       0 |           3 |           3 |                 24
w=cogunluk   |        10 |        28 |      16 |           3 |           0 |                 18
w=hepsi      |        16 |         4 |      40 |           3 |           0 |                  0

okuma tarafi (yazma ilgisi w=1 sabit; kirpma siniri: kayit 17):
okuma yonu | okuma ilgisi | yanitsiz | bayat okuma | ortalama gerilik | geri alinacak veriyi goren
-----------|--------------|----------|-------------|------------------|---------------------------
birincil   | yerel        |        3 |        0/45 |             0.00 |                          3
birincil   | cogunluk     |        3 |       44/45 |             7.82 |                          0
ikincil    | yerel        |        0 |       48/48 |             4.06 |                          0
ikincil    | cogunluk     |        0 |       48/48 |             8.69 |                          0

kosumdan bagimsiz: onay turu, ikincillerin uzaklik siralamasindaki (w-1). degerin
iki katidir. Bu kumede siralama 3 < 5 < 6 < 8, yani w buyudukce onay turu
6, 10, 12, 16 degerlerini alir; hicbir w'de azalmaz.
```

## Kayıp Yazma, Geri Alınan Yazmadan Başkadır

Birinci tablonun iki sütunu birbirine benziyor ve aynı şey değil. **Geri alınan yazma** üç
ayarda da 3'tür; bu, kümenin bir olgusudur ve ayarla değişmez, çünkü eski birincilin yazdığı ama
hiçbir hayatta kalan üyeye ulaşmamış üç kayıt vardır. **Kayıp yazma** ise bunların içinden
çağırana **başarılı diye bildirilmiş** olanlarıdır ve ayarla doğrudan değişir: `w=1` ayarında 3,
`w=çoğunluk` ve `w=hepsi` ayarlarında 0.

`w=çoğunluk` ayarının kayıp yazmayı sıfırlaması bir tesadüf değil, önceki dersteki seçim
kuralının doğrudan sonucudur. Bir yazma çoğunluğa ulaştıysa, yeni birincil olabilecek her üye o
çoğunluğun içinden gelir; aday oy veren çoğunluktan geride olamayacağı için o yazma yeni
birincilde de vardır. Yazma ilgisi ile seçim kuralı aynı sayının iki ucudur.

Bedel onay turu sütunundadır: 0 tura karşılık 10 tur. Bu sayı koşuma bağlı değildir; son bloktaki
satır onu türetiyor. Onay turu, ikincillerin uzaklık sıralamasındaki `(w-1)`. değerin iki
katıdır. Bu kümede sıralama 3, 5, 6, 8 olduğu için w büyüdükçe onay turu 6, 10, 12, 16 değerlerini
alır ve hiçbir adımda azalmaz. Onay düzeyini yükseltmek yazmayı yavaşlatmakla kalmaz — **hangi
üyenin yavaş olduğunu doğrudan çağıranın beklediği süreye çevirir**.

## Tümünden Onay İstemenin Bedeli

`w=hepsi` satırı en sert sonucu veriyor. Arıza öncesinde 20 yazmanın yalnız 4'ü onaylandı;
arızadan sonra ise **hiçbiri** onaylanmadı. Sebep aritmetiktir: bir üye kapalıyken "bütün üyeler"
koşulu hiçbir zaman sağlanamaz. Beş üyeli bir kümede tek bir üyenin kaybı, `w=hepsi` ayarında
yazmayı tamamen durdurur.

Bu satır, onay düzeyinin "yüksek olması iyidir" biçiminde okunamayacağını gösteriyor. `w=hepsi`
kayıp yazmayı sıfırlar ama bunu 40 onaysız yazmayla ve arıza sonrası sıfır verimle satın alır.
`w=çoğunluk` aynı sıfır kaybı 16 onaysız yazmayla ve arıza sonrası 18 onaylı yazmayla sağlar.
Çoğunluk kuralı burada da tepe noktasıdır: onay düzeyini çoğunluğun üstüne çıkarmak dayanıklılık
eklemez, yalnız kırılganlık ekler.

Onaysız kalan yazmalar veri kaybı değildir; çağıranın **ne olduğunu bilmediği** yazmalardır. Bir
ödünç kaydı üyenin hesabına geçmiş de olabilir, geçmemiş de. Yeniden denenebilir olması, ödünç
verme işleminin kendisinin yinelenebilir tasarlanmasını gerektirir.

## Okuma Yönü ve Okuma İlgisi

İkinci tablo dört bileşimi aynı senaryoda karşılaştırıyor ve dördü de farklı bir bedel ödüyor.

`birincil` + `yerel`: 45 yanıtın hiçbiri bayat değil, ortalama gerilik 0,00. Buna karşılık 3 okuma
**sonradan geri alınacak veriyi gördü** ve 3 istek arıza penceresinde yanıtsız kaldı. Bu ayar en
güncel yanıtı verir ve en çok yanılma riskini taşır: ödünç ekranında görünen kayıt, birkaç tur
sonra hiç var olmamış hâle gelebilir.

`birincil` + `çoğunluk`: geri alınacak veriyi gören okuma 0'a iniyor. Bedel bayat okuma
sütunundadır — 45 yanıtın 44'ü bayat ve ortalama gerilik 7,82 ödünç kaydı. Çoğunluk okuması
"doğru" değeri vermez; **geri alınmayacak** değeri verir ve bunun için çoğunluğun yetişmesini
bekler.

`ikincil` yönlü iki satırın ortak kazancı yanıtsız sütunundadır: 0. İkincilden okuyan bir istek,
birincil düştüğünde ve seçim sürerken de yanıt alır. Kütüphane katalog aramaları için doğru ayar
budur. Bedeli iki satırda da bayatlıktır: `yerel` ile 4,06, `çoğunluk` ile 8,69 kayıt gerilik.
İkincil yönü çoğunluk okumasıyla birleştirmek iki bekleme kaynağını üst üste koyar — üyenin kendi
gerikliği artı çoğunluğun taahhüt gecikmesi.

Buradan çıkan kural işlem başına ayar yapmaktır. Ödünç verme yazması `w=çoğunluk` ile yazılır ve
üyeye "kitap sizde" denmeden önce çoğunluk beklenir; aynı kaydın kataloğa yansıması `ikincil` +
`yerel` ile okunur ve dört kayıtlık gerilik kabul edilir.

## Özet

- Yazma ilgisi ile okuma ilgisi ayarlardır ve istek başına verilir; onay düzeyi, bir yazmanın
  başarılı sayılması için gereken üye sayısıdır.
- Geri alınan yazma üç ayarda da 3 çıktı — bu kümenin olgusudur; kayıp yazma ayarla değişti:
  `w=1` ile 3, `w=çoğunluk` ve `w=hepsi` ile 0.
- Onay turu koşumdan bağımsız türetilir: ikincillerin uzaklık sıralamasındaki `(w-1)`. değerin iki
  katı — bu kümede 6, 10, 12, 16 ve hiçbir adımda azalmaz.
- `w=hepsi` ayarında tek bir üyenin kaybı yazmayı tamamen durdurdu: arıza sonrası onaylanan yazma
  0, toplam onaysız 40. Çoğunluğun üstüne çıkmak dayanıklılık eklemedi.
- Okuma ayarlarının dört bileşimi dört ayrı bedel ödedi: `birincil`+`yerel` 3 yanıtsız istek ve
  geri alınacak veriyi gören 3 okuma; `birincil`+`çoğunluk` 44/45 bayat ve 7,82 gerilik;
  `ikincil` yönü 0 yanıtsız ama 48/48 bayat.
- Okuma yönü ile okuma ilgisi ayrı ayarlardır; ikisini birleştirmek iki bekleme kaynağını üst üste
  koyar (4,06'ya karşı 8,69 gerilik).

## Sonraki Adım

Bu dersin tablolarında adı konmamış bir şey var. `w=çoğunluk` ile `çoğunluk` okumasının birlikte
verdiği güvenceyle, `w=1` ile `yerel` okumanın verdiği güvence aynı adı taşımaz; ikisinin arasında
duran bileşimler de vardır ve her biri ayrı bir söz verir. Bu sözlerin adları Sistem Tasarımına
Giriş kursunda tanımlandı: güçlü tutarlılık, sonunda tutarlılık, monotonik okuma ve kendi
yazdığını okuma. Tanımlar orada kaldı; burada eksik olan, hangi ayar bileşiminin hangi sözü
verdiğidir. Sonraki ders bu eşlemeyi kurar, aralarına listede bulunmayan bir modeli — nedensel
tutarlılığı — ekler ve aynı üye oturumunu altı ayar bileşiminde koşturarak kendi yazdığını
okuyamama sayısını, monotonik ihlali, nedensel bağın koptuğu okuma sayısını ve her güvencenin
bedelini oluşturan bekleme turlarını sayar.
