---
title: 'Ekleme Günlüğü Kalıcılığı'
source: 'https://academia.sh/tr/kurslar/bellek-ici-depolar/ekleme-gunlugu-kaliciligi'
course: 'Bellek İçi Depolar ve Önbellek Sistemleri'
language: tr
updated: '2026-08-17T18:08:58+00:00'
license: 'CC BY-SA 4.0'
---

# Ekleme Günlüğü Kalıcılığı

Durumun değil yazmanın kaydedildiği kalıcılık biçimi: komut günlüğünün yazma başına kaç bayt tuttuğu, günlüğün anlık görüntüye oranla nasıl büyüdüğü, yeniden yazımın kazandırdığı yer ve her komutta, saniyede bir ya da işletim sistemine bırakarak eşzamanlamanın kayıp penceresiyle yazma maliyetine etkisi.

Anlık görüntü, deponun bir andaki hâlini yazar. İki an arasında olan biten hiçbir yere
kaydedilmez, bu yüzden kayıp penceresi aralık ne kadar kısaltılırsa kısaltılsın sıfıra
inmez. Kütüphanenin ödünç sayaçları için bu, en kötü durumda binlerce ödünç kaydının elle
geri toplanması demektir.

Bu ders ikinci biçimi ele alır: durumu değil **yazmayı** kaydetmek. Her değiştirici komut,
uygulandığı sırayla bir dosyanın sonuna eklenir. Kurtarma, boş bir depo üzerinde bu komutları
yeniden oynatır. Dosyanın sonuna eklemekten başka bir işlem yapılmadığı için yazma yolu
ucuzdur; bedeli iki yerde çıkar: dosya durmadan büyür ve "eklendi" ile "diskte" arasındaki
fark bir ayara dönüşür.

## Yazmanın Kendisini Kaydetmek

Kayıt biçimi deponun komutunu olduğu gibi taşır: komut harfi, anahtar, değer. Yük önceki
dersle aynıdır — yirmi bin üyeye dağılan altmış bin ödünç yazması, aynı tohumla — böylece
iki biçimin sayıları doğrudan karşılaştırılabilir.

```js
// gunluk.mjs — komut günlüğü kaydı ve aynı ödünç yükü
export const kayit = (a, d) => `Y\t${a}\t${d}\n`;   // Y: yazma komutu

export function uretec(tohum) {
  let a = tohum >>> 0;
  return () => {
    a = (a + 0x6d2b79f5) >>> 0;
    let t = a;
    t = Math.imul(t ^ (t >>> 15), t | 1);
    t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
    return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
  };
}

export function yukUret(sayi, tohum, uyeSayisi = 20000) {
  const r = uretec(tohum), liste = [];
  for (let i = 0; i < sayi; i++) {
    const u = Math.floor(r() * uyeSayisi);
    liste.push([
      'odunc:u' + String(u).padStart(5, '0'),
      `sube=${1 + (u % 8)};gun=${[7, 14, 28][i % 3]};yenileme=${i % 4}`,
    ]);
  }
  return liste;
}
```

## Günlüğün Büyümesi ve Yeniden Yazım

Aşağıdaki koşum yükü gerçekten diske yazar ve yirmi binde bir durup iki büyüklüğü yan yana
koyar: o ana kadarki günlük dosyası ve aynı durumun anlık görüntüsü.

```js
// buyume.mjs — günlüğün büyümesi ve yeniden yazımın kazandırdığı yer
import { appendFileSync, writeFileSync, statSync, rmSync } from 'node:fs';
import { kayit, yukUret } from './gunluk.mjs';

const YUK = yukUret(60000, 20260731);
rmSync('odunc.log', { force: true });
const durum = new Map();
let tampon = '', gunlukBayt = 0;
console.log('yazma   günlük bayt  anahtar  görüntü bayt  günlük/görüntü');
for (let i = 0; i < YUK.length; i++) {
  const [a, d] = YUK[i];
  tampon += kayit(a, d);                       // her yazma günlüğün sonuna eklenir
  durum.set(a, d);
  if ((i + 1) % 20000 === 0) {
    appendFileSync('odunc.log', tampon);
    gunlukBayt += Buffer.byteLength(tampon);
    tampon = '';
    let g = 0;
    for (const [k, v] of durum) g += Buffer.byteLength(k) + Buffer.byteLength(v) + 2;
    console.log(String(i + 1).padStart(5), String(gunlukBayt).padStart(12),
      String(durum.size).padStart(8), String(g).padStart(13),
      (gunlukBayt / g).toFixed(2).padStart(15));
  }
}
console.log('dosya:', statSync('odunc.log').size, 'bayt,', YUK.length, 'kayıt,',
  (statSync('odunc.log').size / YUK.length).toFixed(1), 'bayt/yazma');

let yeni = '';                                  // yeniden yazım: yalnız yaşayan anahtarlar
for (const [a, d] of durum) yeni += kayit(a, d);
writeFileSync('odunc-yeni.log', yeni);
const eski = statSync('odunc.log').size, sonra = statSync('odunc-yeni.log').size;
console.log('yeniden yazım:', durum.size, 'kayıt,', sonra, 'bayt |',
  'kazanç', eski - sonra, 'bayt (%' + (((eski - sonra) / eski) * 100).toFixed(1) + ')');
```

```
yazma   günlük bayt  anahtar  görüntü bayt  günlük/görüntü
20000       793333    12717        479015            1.66
40000      1586666    17330        652842            2.43
60000      2380000    19040        717260            3.32
dosya: 2380000 bayt, 60000 kayıt, 39.7 bayt/yazma
yeniden yazım: 19040 kayıt, 755340 bayt | kazanç 1624660 bayt (%68.3)
```

Yazma başına maliyet sabittir: 39,7 bayt. Günlük dosyası **yazma sayısıyla** doğrusal büyür ve
neyi yazdığına bakmaz; aynı üyenin ödünç kaydının onuncu kez güncellenmesi de dosyaya tam
bir kayıt ekler. Anlık görüntü ise **anahtar sayısıyla** büyür ve üzerine yazılan değerlerin
geçmişini taşımaz. Son sütun aradaki makası verir: yirmi bin yazmada günlük görüntünün 1,66
katıdır, altmış binde 3,32 katı. Kütüphane çalışmayı sürdürdükçe oran büyümeye devam eder,
çünkü paydaki sayı durmaz, paydadaki sayı yirmi bin üyede doyar.

Bu büyüme, ekleme günlüğünün doğrudan sonucudur ve tek çaresi vardır: **yeniden yazım**.
Deponun o anki durumu taranır ve yaşayan her anahtar için tek bir kayıt üretilir; eski dosya
bununla değiştirilir. Ölçümde 60.000 kayıt 19.040 kayda iner, dosya 2.380.000 bayttan 755.340
bayta düşer, kazanç yüzde 68,3'tür.

İki ayrıntı burada okunur. Birincisi, yeniden yazılmış günlük (755.340 bayt) aynı durumun
anlık görüntüsünden (717.260 bayt) tam 38.080 bayt büyüktür; bu, 19.040 kaydın her birine
düşen iki baytlık komut önekidir. Yeniden yazımdan sonra günlük, biçim farkı dışında bir
anlık görüntüdür. İkincisi ve daha önemlisi: yeniden yazım da bütün girişleri taramak
zorundadır. Yani önceki dersteki görüntü alma maliyeti — duraklatmak ya da kopyalamak — bu
yolda da vardır, yalnız daha seyrek ortaya çıkar. Ekleme günlüğü görüntü almayı ortadan
kaldırmaz; ne zaman yapılacağını dosyanın boyutuna bağlar.

## Eşzamanlama Ayarı

Bir kaydın "yazıldı" sayılması üç ayrı yerde gerçekleşebilir. Kayıt önce **uygulamanın kendi
tamponuna** girer. Tampon boşaltıldığında **işletim sisteminin tamponuna** geçer; süreç bu
noktadan sonra çökse bile kayıt yaşar, çünkü onu artık işletim sistemi tutmaktadır. Kaydın
**kalıcı ortama** geçtiğinin garantilenmesi ise ayrı bir istektir; makinenin elektriği
kesildiğinde yalnız o adımı geçmiş kayıtlar durur.

Ayar bu üç durak arasında seçim yapar. Aşağıdaki koşum aynı bin beş yüz kaydı üç kiple yazar
ve koşumdan bağımsız nicelikleri basar: yazma çağrısı sayısı, eşzamanlama sayısı, dosya
boyutu. Süre de ölçülür, ama tek başına bir sayı olarak değil sıralama olarak basılır; süre
diskin türüne ve makinenin yüküne bağlıdır.

**KB3.** Kütüphanenin en yoğun saatinde depoya saniyede 3.000 yazma gelir.
**KB4.** Uygulama tamponu 65.536 bayttır ve işletim sistemi kendi tamponunu beş saniyede bir
kalıcı ortama geçirir.

```js
// eszamanlama.mjs — üç eşzamanlama ayarının maliyeti ve kayıp penceresi
import { openSync, writeSync, fsyncSync, closeSync, statSync, rmSync } from 'node:fs';
import { kayit, yukUret } from './gunluk.mjs';

const N = 1500, HIZ = 3000, TAMPON = 65536, GERIYAZMA = 5;   // KB3, KB4
const YUK = yukUret(N, 20260731);

function kos(ad, donem, tamponla) {
  rmSync(ad, { force: true });
  const fd = openSync(ad, 'w');
  let cagri = 0, es = 0, t = '', tb = 0;
  const bas = process.hrtime.bigint();
  for (let i = 0; i < N; i++) {
    const s = kayit(YUK[i][0], YUK[i][1]);
    if (tamponla) {                              // uygulama tamponu dolunca yazılır, eşzamanlama yok
      t += s; tb += Buffer.byteLength(s);
      if (tb >= TAMPON) { writeSync(fd, t); cagri++; t = ''; tb = 0; }
    } else {
      writeSync(fd, s); cagri++;
      if ((i + 1) % donem === 0) { fsyncSync(fd); es++; }
    }
  }
  if (t) { writeSync(fd, t); cagri++; }
  if (!tamponla && N % donem !== 0) { fsyncSync(fd); es++; }
  const sure = Number(process.hrtime.bigint() - bas);
  closeSync(fd);
  return { cagri, es, bayt: statSync(ad).size, sure };
}

const kipler = [
  ['her yazmada', kos('a.log', 1, false)],
  ['saniyede bir', kos('b.log', HIZ, false)],
  ['işletim sistemine bırak', kos('c.log', 0, true)],
];
console.log(`ölçüm: ${N} kayıt, aynı içerik, üç kip`);
console.log('kip                      yazma çağrısı  eşzamanlama  dosya baytı');
for (const [ad, s] of kipler)
  console.log(ad.padEnd(24), String(s.cagri).padStart(13), String(s.es).padStart(12),
    String(s.bayt).padStart(12));
console.log('süre sıralaması (yavaştan hızlıya):',
  [...kipler].sort((x, y) => y[1].sure - x[1].sure).map(([a]) => a).join(', '));

const bpk = kipler[0][1].bayt / N;              // kayıt başına bayt
const T = 60000;
console.log(`\n${T} yazmalık yük, saniyede ${HIZ} yazma, ${TAMPON} baytlık tampon,`,
  `${GERIYAZMA} saniyelik geri yazma`);
console.log('kip                      eşzamanlama  en kötü kayıp  ortalama kayıp');
const satir = (ad, es, kotu) => console.log(ad.padEnd(24), String(es).padStart(11),
  String(kotu).padStart(14), String(Math.round(kotu / 2)).padStart(15));
satir('her yazmada', T, 0);
satir('saniyede bir', Math.ceil(T / HIZ), HIZ);
satir('işletim sistemine bırak', 0, Math.floor(TAMPON / bpk) + GERIYAZMA * HIZ);
```

```
ölçüm: 1500 kayıt, aynı içerik, üç kip
kip                      yazma çağrısı  eşzamanlama  dosya baytı
her yazmada                       1500         1500        59500
saniyede bir                      1500            1        59500
işletim sistemine bırak              1            0        59500
süre sıralaması (yavaştan hızlıya): her yazmada, saniyede bir, işletim sistemine bırak

60000 yazmalık yük, saniyede 3000 yazma, 65536 baytlık tampon, 5 saniyelik geri yazma
kip                      eşzamanlama  en kötü kayıp  ortalama kayıp
her yazmada                    60000              0               0
saniyede bir                      20           3000            1500
işletim sistemine bırak            0          16652            8326
```

Üç kip aynı dosyayı üretir: 59.500 bayt, aynı içerik. Ayrılan tek şey, o baytların ne zaman
ve hangi garantiyle yerine geçtiğidir.

**Her yazmada** eşzamanlama, altmış bin yazmalık yükte altmış bin ayrı eşzamanlama demektir
ve kayıp penceresini sıfıra indirir. Bu ölçümün alındığı makinede eşzamanlama başına yaklaşık
3,8 milisaniye harcandı; sayı diske ve yüke göre değişir, bu yüzden çıktıya süre değil sıralama
basıldı. Değişmeyen nicelik eşzamanlama sayısıdır ve tabloda üç kip arasındaki fark dört
büyüklük mertebesindedir. Sıfır kayıp penceresinin bir koşulu daha vardır: eşzamanlama, yanıt
istemciye dönmeden **önce** bitmelidir. Kayıt diske geçmeden "ödünç alındı" yanıtı verilirse
pencere yeniden açılır.

**Saniyede bir** eşzamanlama, aynı yükte yirmi eşzamanlamaya iner; yazma yolundan üç bin kat
daha az bekleme çıkarır. Karşılığında en kötü durumda bir saniyelik iş, yani 3.000 ödünç
yazması yiter. Ortalama kayıp bunun yarısıdır.

**İşletim sistemine bırakmak** eşzamanlamayı tümüyle kaldırır ve yazma çağrısı sayısını da
düşürür: bin beş yüz kayıt tek bir çağrıyla yazıldı, çünkü hepsi 65.536 baytlık tampona sığdı.
En ucuz kip budur ve en kötü kaybı da odur: 16.652 yazma. Bu sayının nereden geldiği önemli,
çünkü iki ayrı gecikme toplanıyor — uygulama tamponundaki 1.652 kayıt ve işletim sistemine
verilmiş olup henüz kalıcı ortama geçmemiş beş saniyelik iş.

## Ayarın Karşılığı

Üç ayar aynı sorunun üç yanıtıdır: bir ödünç yazmasının kaybının bedeli, o yazmayı diske
geçirmenin bedelinden büyük mü? Kütüphanenin oturum kayıtları için değildir; oturumu yiten
görevli yeniden açar. Ödünç sayaçları için sınırdadır. Ceza hesabına giren gecikme
kayıtları için büyüktür, çünkü kaybedilen kayıt paraya karşılık gelir ve geri toplanamaz.

Ekleme günlüğünün anlık görüntüye karşı asıl üstünlüğü, kayıp penceresini **yazma başına**
ayarlanabilir kılmasıdır. Bedeli de dosyanın boyutudur: aynı durum için 3,32 kat yer, ve o
yeri geri almak için düzenli yeniden yazım. İki biçimin birbirinin eksiğini kapattığı buradan
görünür, ama hangisinin ne zaman seçileceği henüz tek bir tabloda toplanmadı.

## Özet

- Ekleme günlüğü durumu değil komutu kaydeder; ölçümde yazma başına 39,7 bayt tuttu ve
  dosya yazma sayısıyla doğrusal büyüdü.
- Günlük yazma sayısıyla, anlık görüntü anahtar sayısıyla büyür: aynı veri için oran 20.000
  yazmada 1,66, 60.000 yazmada 3,32 kat oldu.
- Yeniden yazım 60.000 kaydı 19.040 kayda indirdi ve dosyayı yüzde 68,3 küçülttü; sonuçta
  ortaya çıkan dosya, iki baytlık komut öneki dışında bir anlık görüntüdür ve aynı tam tarama
  maliyetini taşır.
- Eşzamanlama ayarı kayıp penceresini belirler: her yazmada 0 yazma ve 60.000 eşzamanlama;
  saniyede bir 3.000 yazma ve 20 eşzamanlama; işletim sistemine bırakıldığında 16.652 yazma
  ve hiç eşzamanlama.
- Üç kip aynı 59.500 baytlık dosyayı üretti; aralarındaki fark içerikte değil, kaydın hangi
  durakta durduğu garantisindedir.

## Sonraki Adım

İki kalıcılık biçimi de ölçüldü ve ikisinin de kendi başına eksik kaldığı görüldü: anlık
görüntü kayıp penceresini kapatamıyor, ekleme günlüğü boyutunu tutamıyor. Sonraki ders
seçimi tek bir tabloda toplar. Üç ölçü karşılaştırılır: sürecin yeniden başlamasından
hizmete hazır olmasına kadarki kurtarma adımı, kayıp penceresi ve sürekli maliyet. İki
yolun **birlikte** kullanıldığı düzen de aynı tabloya girer — görüntü tabanı, üzerine son
görüntüden sonraki kayıtlar — ve bu düzenin kurtarmayı neden hem kısalttığı hem de kayıp
penceresini dar tuttuğu sayıyla gösterilir.
