İçeriğe geç
academia.sh

Ders 04 / 25

Denetim Noktaları

Günlükteki değişikliklerin veri dosyasına işlenmesi, denetim noktasının veri dosyasını ve günlük dosyasını nasıl değiştirdiği, günlüğün yeniden kullanılması ile kısaltılması arasındaki fark, denetim noktası sıklığının yazma maliyeti ile kurtarma işi arasındaki ödünleşimi ve okuyucuların denetim noktasını nasıl geciktirdiği.

İçindekiler

Önceki derste günlük dosyası büyüdü ve hiç küçülmedi, çünkü kendiliğinden denetim noktası kapatılmıştı. Bu durum uzun süre sürdürülemez. Sınırsız büyüyen bir günlük diski doldurur; üstelik açılışta okunması gereken kayıt sayısı arttıkça kurtarma uzar. Veri dosyası ise günlerce hiç değişmeden durabilir ve içindeki bilgi giderek eskir.

Bu iki dosyanın er geç eşitlenmesi gerekir. Denetim noktası (checkpoint), bu eşitlemenin adıdır. Dersin soruları şunlardır: eşitleme sırasında hangi dosya nasıl değişir, günlük niçin bazen kısalıp bazen kısalmaz ve bu işlem ne sıklıkta yapılmalıdır?

Denetim Noktası Ne Yapar

Denetim noktası, günlükte biriken değişiklikleri veri dosyasındaki sayfalara işler. Adım sırası kısadır: günlükteki kayıtlar okunur, karşılık gelen sayfaların son hâli veri dosyasına yazılır, yazmanın kalıcı olduğu doğrulanır ve ancak ondan sonra o günlük alanı serbest sayılır.

Sıralama zorunludur. Günlük alanı, veri dosyası yazması kalıcı olmadan serbest bırakılırsa ortada iki kopya da bulunmayan bir değişiklik kalır. Yazma öncesi kuralın ikinci yüzü budur: günlük kaydı veri sayfasından önce kalıcı olur, günlük alanı ise veri sayfasından sonra serbest kalır.

Bir sınırlama daha vardır. Denetim noktası, o anda okuma yapan işlemlerin gördüğü sayfaların üzerine yazamaz; bir sonraki ders bunun nedenini kuracaktır. Bu yüzden uzun süren bir okuma denetim noktasını geciktirebilir ve günlük bu sırada büyümeye devam eder. Yönetimde karşılaşılan “günlük neden şişti” sorusunun sık rastlanan cevaplarından biri, unutulmuş bir uzun okuma işlemidir.

Ölçülen Denetim Noktası

Aşağıdaki koşum, denetim noktasından önceki ve sonraki durumu üç ölçüyle karşılaştırır: veri dosyasının boyutu, günlük dosyasının boyutu ve veritabanının mantıksal sayfa sayısı.

rm -f n.db n.db-wal n.db-shm
sqlite3 n.db <<'SQL'
CREATE TABLE odunc(odunc_id INTEGER PRIMARY KEY, kitap_id INT, uye_id INT,
                   alis_tarihi TEXT, iade_tarihi TEXT);
INSERT INTO odunc SELECT n, 1+(n*7)%200000, 1+(n*13)%120000, '2024-01-01', NULL
  FROM (WITH RECURSIVE s(n) AS (SELECT 1 UNION ALL SELECT n+1 FROM s WHERE n<50000) SELECT n FROM s);
PRAGMA journal_mode = WAL;
PRAGMA wal_autocheckpoint = 0;
INSERT INTO odunc SELECT 100000+n, 1+(n*7)%200000, 1+(n*13)%120000, '2024-03-01', NULL
  FROM (WITH RECURSIVE s(n) AS (SELECT 1 UNION ALL SELECT n+1 FROM s WHERE n<20000) SELECT n FROM s);
.shell echo "--- denetim noktasi oncesi ---"
.shell echo "veri: $(wc -c < n.db)  gunluk: $(wc -c < n.db-wal)"
SELECT 'veri dosyasindaki sayfa sayisi', page_count FROM pragma_page_count;
PRAGMA wal_checkpoint(PASSIVE);
.shell echo "--- PASSIVE denetim noktasi sonrasi ---"
.shell echo "veri: $(wc -c < n.db)  gunluk: $(wc -c < n.db-wal)"
SELECT 'veri dosyasindaki sayfa sayisi', page_count FROM pragma_page_count;
PRAGMA wal_checkpoint(TRUNCATE);
.shell echo "--- TRUNCATE denetim noktasi sonrasi ---"
.shell echo "veri: $(wc -c < n.db)  gunluk: $(wc -c < n.db-wal)"
SQL
wal
0
--- denetim noktasi oncesi ---
veri:  1380352  gunluk:   580952
veri dosyasindaki sayfa sayisi|475
0|141|141
--- PASSIVE denetim noktasi sonrasi ---
veri:  1945600  gunluk:   580952
veri dosyasindaki sayfa sayisi|475
0|0|0
--- TRUNCATE denetim noktasi sonrasi ---
veri:  1945600  gunluk:        0

Denetim noktasından önce veri dosyası 1.380.352 bayt, yani 337 sayfa. Ama sorgu sayfa sayısını 475 olarak veriyor. Veri dosyasında hiç bulunmayan 138 sayfa günlüktedir. Bu, ilk dersteki mimarinin somut hâlidir: veritabanının mantıksal durumu, veri dosyası ile günlüğün birleşiminden okunur; veri dosyası tek başına eski bir andır.

PRAGMA wal_checkpoint çıktısı üç sayı verir: engellenme durumu, günlükteki çerçeve sayısı ve işlenen çerçeve sayısı. İlk çağrıda 0|141|141 — engellenme yok, günlükte 141 çerçeve var, hepsi işlendi. Çerçeve sayısı dosya boyutuyla doğrulanabilir: her çerçeve bir sayfa artı 24 baytlık başlıktır ve dosyanın başında 32 baytlık bir bölüm bulunur; 32 + 141 × (4096 + 24) = 580.952, ölçülen boyutun aynısı. Çerçeve sayısının 138’den fazla olması, bazı sayfaların günlükte birden çok kez yer almasındandır: eklemeler sırasında ağacın üst düzeyleri de değişir ve her değişiklik ayrı bir çerçeve yazar.

Denetim noktasından sonra veri dosyası 1.945.600 bayta çıktı: tam 475 sayfa. Mantıksal sayfa sayısı değişmedi, çünkü veri değişmedi — yalnız yeri değişti. İkinci çağrı 0|0|0 döndürüyor: işlenecek bir şey kalmamış.

Yeniden Kullanma ve Kısaltma

İlk denetim noktasından sonra günlük dosyasının boyutu 580.952 baytta kaldı; içi işlenmiş olduğu hâlde dosya küçülmedi. Bu bir kusur değil, kasıtlı bir davranıştır: işlenmiş bir günlük dosyası baştan yeniden yazılabilir. Dosyayı kısaltıp sonra yeniden büyütmek, dosya sistemine gereksiz iş çıkarır; aynı alanın üzerine yazmak ucuzdur.

İkinci çağrıdaki TRUNCATE biçimi dosyayı gerçekten sıfırlar. Bunun yeri, günlüğün bir kereye mahsus şiştiği ve alanın geri istendiği durumlardır. Sürekli çalışan bir sistemde günlük dosyasının belli bir boyutta durması beklenen davranıştır; sürekli sıfırlanması değil.

Buradaki biçim adları (PASSIVE, TRUNCATE) bu araca özgüdür. Ayrımın kendisi — işlenmiş günlük alanının yeniden kullanılması ile dosyanın kısaltılması — motordan bağımsızdır.

Sıklık Ödünleşimi

Denetim noktası ne sıklıkta alınmalıdır? Soru bir ayar değeri sorusu gibi görünür; aslında iki maliyet arasında bir seçimdir. Sık denetim noktası, aynı sayfayı defalarca veri dosyasına yazar ve yazma yolunu ağırlaştırır. Seyrek denetim noktası, günlüğün büyümesine ve kurtarmanın uzamasına yol açar.

Aşağıdaki koşum eşiği değiştirerek beş bin küçük işlemi ölçer ve iki sonucu yan yana koyar: geçen süre ve işlem sonunda günlükte kalan çerçeve sayısı. İkinci sayı, bir çökme olsaydı kurtarmanın işlemek zorunda kalacağı iş miktarıdır.

cat > sikilik.mjs <<'JS'
import { DatabaseSync } from 'node:sqlite';
import { rmSync, statSync } from 'node:fs';

const CERCEVE = 4096 + 24;                       // sayfa + cerceve basligi
function olc(esik) {
  for (const ek of ['', '-wal', '-shm']) rmSync('s.db' + ek, { force: true });
  const db = new DatabaseSync('s.db');
  db.exec('PRAGMA journal_mode = WAL');
  db.exec('PRAGMA synchronous = NORMAL');
  db.exec('CREATE TABLE odunc(odunc_id INTEGER PRIMARY KEY, uye_id INT, iade_tarihi TEXT)');
  db.exec(`INSERT INTO odunc SELECT n, 1+(n*13)%500, NULL
           FROM (WITH RECURSIVE s(n) AS (SELECT 1 UNION ALL SELECT n+1 FROM s WHERE n<20000) SELECT n FROM s)`);
  db.exec('PRAGMA wal_checkpoint(TRUNCATE)');
  db.exec(`PRAGMA wal_autocheckpoint = ${esik}`);
  const guncelle = db.prepare('UPDATE odunc SET iade_tarihi = ? WHERE odunc_id = ?');
  const bas = process.hrtime.bigint();
  for (let i = 1; i <= 5000; i++) { db.exec('BEGIN'); guncelle.run('2024-04-01', 1 + (i * 37) % 20000); db.exec('COMMIT'); }
  const sure = Number(process.hrtime.bigint() - bas) / 1e6;
  const cerceve = Math.round((statSync('s.db-wal').size - 32) / CERCEVE);
  db.close();
  return [sure, cerceve];
}
console.log('eşik (sayfa)   5000 işlem (ms)   günlükte kalan çerçeve');
for (const e of [1, 10, 100, 1000, 0]) {
  const [s, c] = olc(e);
  console.log(String(e === 0 ? 'kapalı' : e).padStart(12), s.toFixed(0).padStart(16), String(c).padStart(22));
}
JS
node sikilik.mjs
eşik (sayfa)   5000 işlem (ms)   günlükte kalan çerçeve
           1              327                      6
          10               72                     15
         100               37                    103
        1000               32                   1000
      kapalı               38                   5719

Süreler ortama bağlıdır; ilişkiye oranlar üzerinden bakılır. Her sayfada bir denetim noktası alındığında beş bin işlem, bin sayfalık eşiğe göre yaklaşık on kat uzun sürdü. Karşılığında günlükte yalnız altı çerçeve kaldı: bir çökme neredeyse hiç iş bırakmazdı. Eşik büyüdükçe süre hızla düşüyor ve yüz sayfadan sonra yassılaşıyor; günlükte biriken çerçeve sayısı ise doğrusal olarak artıyor.

Eğrinin biçimi seçimi kolaylaştırır. Çok sık denetim noktası pahalıdır ve karşılığında kazandırdığı kurtarma süresi zaten küçüktür. Çok seyrek denetim noktası ise süreyi daha fazla kısaltmaz — son satırda “kapalı” durumun süresi bin sayfalık eşikten daha iyi değil — ama günlüğü ve kurtarma işini sınırsız büyütür. Verimli aralık ortadadır ve bu, bir başarım ayarından çok bir kurtarma hedefi kararıdır: “çökmeden sonra en fazla ne kadar sürede açılmış olmalıyız” sorusunun cevabı, günlüğün ne kadar birikmesine izin verileceğini belirler.

Kurtarmanın İşi

Denetim noktasının kurtarma tarafındaki etkisi doğrudandır. Açılışta motor, son denetim noktasından sonraki günlük kayıtlarını işlemek zorundadır; denetim noktasından önceki kayıtlar zaten veri dosyasındadır. Kurtarmanın yapacağı iş, tablonun büyüklüğüyle değil, denetim noktasından bu yana biriken kayıt sayısıyla orantılıdır.

Burada bir ölçüm uyarısı gerekir. Bu ortamda kurtarma, günlüğü tarayıp iç dizinini yeniden kurmaktan ibarettir ve dosya işletim sisteminin önbelleğinde olduğu için süresi bu büyüklüklerde ölçülebilir bir değer vermez. Bu yüzden yukarıdaki tabloda süre değil, işin kendisi — çerçeve sayısı — ölçü olarak kullanıldı. Sayfaları veri dosyasına ayrıca yazması gereken motorlarda aynı sayı, kurtarma süresinin doğrudan belirleyicisidir.

Sıklık kararının ikinci yüzü de burada görünür: denetim noktası, biriken sayfaları topluca yazdığı için o an yazma yükünde bir sıçrama üretir. Sürekli çalışan bir sistemde bu sıçrama, gecikme ölçümlerinde düzenli tepeler olarak görünür. Motorlar bunu, denetim noktası işini aralığa yayarak yumuşatır; ayarın adı motora göre değişir, amacı aynıdır.

Özet

  • Denetim noktası, günlükte biriken değişiklikleri veri dosyasındaki sayfalara işler; günlük alanı ancak bu yazma kalıcı olduktan sonra serbest kalır.
  • Veritabanının mantıksal durumu veri dosyası ile günlüğün birleşimidir; ölçümde veri dosyası 337 sayfa iken mantıksal sayfa sayısı 475 çıktı, aradaki fark günlükteydi.
  • İşlenmiş bir günlük dosyası genellikle kısaltılmaz, baştan yeniden yazılır; kısaltma ayrı ve isteğe bağlı bir adımdır.
  • Denetim noktası sıklığı iki maliyet arasında seçimdir: her sayfada denetim noktası almak bu ortamda yaklaşık on kat yavaşlattı, hiç almamak günlükte 5.719 çerçeve biriktirdi.
  • Kurtarmanın işi tablo büyüklüğüyle değil, son denetim noktasından sonra biriken kayıt sayısıyla orantılıdır.

Sonraki Adım

Bu derste bir sınırlama geçildi: denetim noktası, o anda okuma yapan işlemlerin gördüğü sayfaların üzerine yazamaz. Bu cümlenin arkasında, motorun eşzamanlılığı sağlama biçimi duruyor. İleri SQL kursunda bir işlem içindeki okumanın, dışarıdaki kesinleştirmelerden etkilenmediği gözlenmişti; bunun nasıl mümkün olduğu sorulmamıştı. Sonraki ders o mekanizmayı kurar: satırın birden çok sürümünün aynı anda saklanması, hangi işlemin hangi sürümü gördüğünü belirleyen kural ve okuyucu ile yazıcının birbirini engellememesi.

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat