---
title: 'Sistem Kataloğu'
source: 'https://academia.sh/tr/kurslar/veritabani-yonetimi/sistem-katalogu'
course: 'İlişkisel Veritabanı Yönetimi'
language: tr
updated: '2026-08-17T18:08:56+00:00'
license: 'CC BY-SA 4.0'
---

# Sistem Kataloğu

Şema tanımının sorgulanabilir tablolarda tutulması, envanterin ve yönetim kurallarının sorguya çevrilmesi, iki kopya arasındaki şema sapmasının ölçülmesi ve kataloğun neden okunup yazılmadığı.

Bu kursta şimdiye kadar sorulan her soru bir sayıyla yanıtlandı: sayfa sayısı, doluluk,
çerçeve sayısı, isabet oranı. Bu sayıların kaynağı motorun kendi tuttuğu kayıtlardır ve o
kayıtlar özel bir arayüzün arkasında değildir. Motor, şema hakkındaki bilgiyi sıradan
tablolarda tutar ve sıradan sorgularla verir. Bu tabloların bütününe **sistem kataloğu
(system catalog)** denir.

Kataloğun sorgulanabilir olması, yönetim işini bir belge işi olmaktan çıkarır. Hangi
tabloların hangi sütunları taşıdığı, hangi dizinlerin var olduğu, hangi kısıtların
tanımlandığı elle tutulan bir listede değil, veritabanının kendisinde yazılıdır — ve o
liste her zaman günceldir, çünkü değişikliği yapan deyimin kendisi onu günceller.

## Katalog Sıradan Bir Tablodur

Aşağıdaki blok kütüphane şemasını kurar. Şema önceki kurslardan tanıdıktır; buraya
dizinler, bir görünüm ve bir değer denetimi eklenmiştir.

```sh
rm -f kutuphane.db
sqlite3 kutuphane.db <<'SQL'
CREATE TABLE sube (
  sube_id INTEGER PRIMARY KEY,
  ad      TEXT NOT NULL,
  sehir   TEXT NOT NULL
);
CREATE TABLE uye (
  uye_id       INTEGER PRIMARY KEY,
  ad           TEXT NOT NULL,
  eposta       TEXT UNIQUE,
  kayit_tarihi TEXT NOT NULL,
  durum        TEXT NOT NULL DEFAULT 'etkin' CHECK (durum IN ('etkin','askida','kapali'))
);
CREATE TABLE kitap (
  kitap_id   INTEGER PRIMARY KEY,
  baslik     TEXT NOT NULL,
  yazar      TEXT NOT NULL,
  isbn       TEXT UNIQUE,
  sube_id    INTEGER NOT NULL REFERENCES sube(sube_id)
);
CREATE TABLE odunc (
  odunc_id    INTEGER PRIMARY KEY,
  uye_id      INTEGER NOT NULL REFERENCES uye(uye_id),
  kitap_id    INTEGER NOT NULL REFERENCES kitap(kitap_id),
  alis_tarihi TEXT NOT NULL,
  iade_tarihi TEXT
);
CREATE INDEX odunc_uye ON odunc(uye_id);
CREATE INDEX odunc_kitap_tarih ON odunc(kitap_id, alis_tarihi);
CREATE VIEW acik_odunc AS SELECT * FROM odunc WHERE iade_tarihi IS NULL;
INSERT INTO sube VALUES (1,'Merkez','Ankara'),(2,'Bahçelievler','Ankara');
INSERT INTO uye (uye_id,ad,eposta,kayit_tarihi) VALUES (1,'Ayşe','ayse@ornek.test','2023-02-14');
INSERT INTO kitap VALUES (1,'Gökbilim El Kitabı','Y. Aydın','978-0201896831',1);
INSERT INTO odunc VALUES (1,1,1,'2025-06-01',NULL);
SQL
```

Şemadaki nesnelerin listesi tek bir sorguyla alınır.

```sh
sqlite3 kutuphane.db <<'SQL'
.headers on
.mode column
SELECT type, name, tbl_name FROM sqlite_schema ORDER BY type, name;
SQL
```

```
type   name                      tbl_name  
-----  ------------------------  ----------
index  odunc_kitap_tarih         odunc     
index  odunc_uye                 odunc     
index  sqlite_autoindex_kitap_1  kitap     
index  sqlite_autoindex_uye_1    uye       
table  kitap                     kitap     
table  odunc                     odunc     
table  sube                      sube      
table  uye                       uye       
view   acik_odunc                acik_odunc
```

Listede yazılmayan iki satır dikkat çeker: `sqlite_autoindex_` önekli dizinler. Bunları
tanımlayıcı yazmadı; benzersizlik kısıtını uygulayabilmek için motor kendisi oluşturdu.
Katalog, yalnız yazılanı değil **motorun kurduğu** yapıyı da gösterir. Bu ayrım
yönetimde işe yarar: bir sütunun benzersiz olması, arka planda bir dizin maliyeti
demektir ve o maliyet burada görünür.

Nesne adlarının önekli ayrılması bir gelenektir ve motora göre değişir; değişmeyen, iç
nesnelerin de katalogda bulunmasıdır.

## Envanteri Sorguyla Çıkarmak

Katalog sorgulanabilir olduğu için, şema hakkındaki her soru bir sorguya çevrilebilir.
Aşağıdaki sorgu tablo başına sütun ve kısıt sayımını üretir.

```sh
sqlite3 kutuphane.db <<'SQL'
.headers on
.mode column
-- Sema envanteri: tablo basina sutun ve kisit sayilari.
SELECT m.name AS tablo, count(*) AS sutun, sum(ti."notnull") AS not_null,
       sum(ti.pk > 0) AS birincil_anahtar
FROM sqlite_schema m JOIN pragma_table_info(m.name) ti
WHERE m.type='table' GROUP BY m.name ORDER BY m.name;
SQL
```

```
tablo  sutun  not_null  birincil_anahtar
-----  -----  --------  ----------------
kitap  5      3         1               
odunc  5      3         1               
sube   3      2         1               
uye    5      3         1
```

Bu tablo bir şema tasarımı tartışmasının başlangıç noktasıdır: hangi tablo kaç sütun
taşıyor, kaç sütun zorunlu, birincil anahtarı olmayan tablo var mı. Elle tutulan bir
belgede bu üç soru için üç ayrı bölüm gerekir ve üçü de eskir; katalogdan çıkarıldığında
sorgu her çalıştırıldığında güncel yanıtı verir.

## Katalogla Yazılan Denetimler

Kataloğun asıl değeri, **kural**ların sorgu olarak yazılabilmesidir. Dizinler ve
Bölümleme konusunda görülecek bir kuralı şimdiden uygulayalım: yabancı anahtar taşıyan
her sütunun kendi dizini olmalıdır, yoksa ana tablodaki silme ve güncelleme işlemleri
çocuk tabloyu baştan sona taramak zorunda kalır.

```sh
sqlite3 kutuphane.db <<'SQL'
.headers on
.mode column
-- 1. Yabanci anahtari dizinsiz kalan sutunlar: silme ve guncelleme maliyetini artirir.
SELECT m.name AS tablo, f."from" AS sutun, f."table" AS hedef
FROM sqlite_schema m
JOIN pragma_foreign_key_list(m.name) f
WHERE m.type = 'table'
  AND NOT EXISTS (
    SELECT 1 FROM pragma_index_list(m.name) il
    JOIN pragma_index_info(il.name) ii
    WHERE ii.seqno = 0 AND ii.name = f."from"
  );
SQL
```

```
tablo  sutun    hedef
-----  -------  -----
kitap  sube_id  sube
```

Denetim tek bir bulgu üretti: kitap tablosundaki şube başvurusu dizinsiz. Ödünç
tablosundaki iki başvuru kapsanıyor — biri kendi dizinine, diğeri bileşik dizinin ilk
sütunu olduğu için ona dayanıyor. Bileşik dizinin yalnız **ilk** sütununun bu işi
gördüğü, Sorgu Başarımı konusunda kurulan kuralın buradaki karşılığıdır.

Bu denetimin elle tutulan listeye üstünlüğü üç noktadadır. Yeni bir tablo eklendiğinde
denetim onu kendiliğinden kapsar. Bir dizin kaldırıldığında bulgu kendiliğinden geri
gelir. Ve denetim, tanımlayıcının ne yazdığını değil motorun ne bildiğini okur — ikisi
ayrıştığında ayrışma görünür olur.

Aynı kalıpla yazılabilecek başka denetimler vardır: birincil anahtarı olmayan tablolar,
hiç kullanılmayan dizinler, aynı sütun listesini paylaşan yinelenen dizinler, değer
denetimi olmayan durum sütunları. Her biri bir yönetim kuralının sorgu biçimidir.

## Şema Sapmasının Ölçülmesi

Katalog sorgulanabilir olduğu için iki veritabanının şeması karşılaştırılabilir. Bu,
sürüm yükseltmelerinde ve ortamlar arası tutarlılık denetiminde en sık ihtiyaç duyulan
işlemdir.

```sh
# Iki semanin farki: gelistirme ve uretim kopyalari ayni mi?
sqlite3 uretim.db <<'SQL'
CREATE TABLE sube (sube_id INTEGER PRIMARY KEY, ad TEXT NOT NULL, sehir TEXT NOT NULL);
CREATE TABLE uye (uye_id INTEGER PRIMARY KEY, ad TEXT NOT NULL, eposta TEXT UNIQUE,
                  kayit_tarihi TEXT NOT NULL);
CREATE TABLE kitap (kitap_id INTEGER PRIMARY KEY, baslik TEXT NOT NULL, yazar TEXT NOT NULL,
                    isbn TEXT UNIQUE, sube_id INTEGER NOT NULL REFERENCES sube(sube_id));
CREATE TABLE odunc (odunc_id INTEGER PRIMARY KEY, uye_id INTEGER NOT NULL REFERENCES uye(uye_id),
                    kitap_id INTEGER NOT NULL REFERENCES kitap(kitap_id), alis_tarihi TEXT NOT NULL,
                    iade_tarihi TEXT);
CREATE INDEX odunc_uye ON odunc(uye_id);
SQL

esle() {
  sqlite3 "$1" "SELECT type||' '||name||' ('||coalesce((SELECT group_concat(ti.name||':'||ti.type, ', ')
                  FROM pragma_table_info(m.name) ti), '')||')'
                FROM sqlite_schema m WHERE name NOT LIKE 'sqlite_%' ORDER BY type, name;"
}
esle kutuphane.db > gelistirme.liste
esle uretim.db    > uretim.liste
echo "--- yalniz gelistirmede olan ---"
comm -23 gelistirme.liste uretim.liste
echo "--- yalniz uretimde olan ---"
comm -13 gelistirme.liste uretim.liste
```

```
--- yalniz gelistirmede olan ---
index odunc_kitap_tarih ()
table uye (uye_id:INTEGER, ad:TEXT, eposta:TEXT, kayit_tarihi:TEXT, durum:TEXT)
view acik_odunc (odunc_id:INTEGER, uye_id:INTEGER, kitap_id:INTEGER, alis_tarihi:TEXT, iade_tarihi:TEXT)
--- yalniz uretimde olan ---
table uye (uye_id:INTEGER, ad:TEXT, eposta:TEXT, kayit_tarihi:TEXT)
```

Fark üç kalem gösteriyor. Bir dizin ve bir görünüm yalnız geliştirme kopyasında var.
Üye tablosu ise iki tarafta da var ama **aynı değil**: geliştirmede bir durum sütunu
eklenmiş, üretimde yok. Sütun listesini karşılaştırmaya katmak bu farkı görünür kılar;
yalnız nesne adları karşılaştırılsaydı iki tablo eşit sayılırdı.

Sapmanın yönü de bilgidir. Geliştirmede olup üretimde olmayan bir sütun, henüz
uygulanmamış bir göç demektir. Üretimde olup geliştirmede olmayan bir nesne ise daha
kaygı vericidir: doğrudan üretime yazılmış, sürüm kontrolünde karşılığı olmayan bir
değişikliğe işaret eder.

## Kataloğa Yazmak

Katalog okunur; **elle yazılmaz**. Şema değişikliği veri tanımlama deyimleriyle yapılır
ve katalog güncellemesini motor üstlenir. Katalog tablolarına doğrudan yazmak — bazı
motorlarda teknik olarak olanaklı olsa da — motorun iç tutarlılığını bozar: veri
dosyalarındaki fiziksel düzenle katalogdaki tanım ayrışır ve bu ayrışma çoğu zaman
sonraki bir okumada, tanısı zor bir hata olarak görünür.

Kuralın pratik karşılığı şudur: göçler deyimlerle yazılır ve sürüm kontrolünde durur;
katalog ise bu göçlerin uygulanıp uygulanmadığını **doğrulamak** için okunur.

## Özet

- Sistem kataloğu, şemanın tanımını tutan ve sıradan sorgularla okunabilen tablolardır;
  değişikliği yapan deyimin kendisi onu güncellediği için her zaman günceldir.
- Katalog yalnız yazılanı değil motorun kendiliğinden kurduğu nesneleri de gösterir:
  benzersizlik kısıtının arkasındaki dizin listede görünür.
- Şema hakkındaki her yönetim kuralı bir sorguya çevrilebilir; dizinsiz yabancı anahtar
  denetimi modelde tek bulgu üretti ve yeni tabloları kendiliğinden kapsar.
- İki kopyanın şeması sütun listeleriyle birlikte karşılaştırıldığında sapma görünür
  olur; yalnız nesne adları karşılaştırılırsa değişmiş bir tablo eşit sayılır.
- Katalog okunur, elle yazılmaz: şema değişikliği deyimlerle yapılır, katalog o
  değişikliğin uygulandığını doğrulamak için sorgulanır.

## Sonraki Adım

Motorun içyapısı bu dersle tamamlanıyor: süreçler, sayfalar, günlük, denetim noktaları,
sürüm zincirleri, temizlik ve bunların hepsini kayda geçiren katalog. Bu bölümde bir
bulgu askıda kaldı — dizinsiz yabancı anahtar. Sonraki konu bu bulgunun ait olduğu alanı
açar: dizin türlerinin birbirinden farkı, bileşik dizinde sütun sırasının neden sonucu
değiştirdiği, kısmi ve kapsayan dizinlerin ne zaman kazandırdığı ve bir tablonun
bölümlere ayrılmasının hangi sorunu çözüp hangisini doğurduğu.
