---
title: 'Veri Katmanı'
source: 'https://academia.sh/tr/kurslar/mcp/veri-katmani'
course: 'Model Bağlam Protokolü ve Araç Ekosistemi'
language: tr
updated: '2026-08-17T18:06:40+00:00'
license: 'CC BY-SA 4.0'
---

# Veri Katmanı

İstek, yanıt ve bildirim mesajlarının bedelinin sayılması: sekiz abonelik bir toplu iş protokolsüz kurulumda 24 işlev çağrısı, sıfır mesaj ve sıfır zarf belirteciyle biterken protokollü kurulumda 48 mesaja, 640 belirtece ve 32 gidiş-dönüşe çıkar ve 640 belirtecin 384'ü yalnız zarftır. Aynı ilerleme bilgisi istek-yanıt çiftiyle taşındığında toplam 1147 belirteç ile 80 gidiş-dönüş, bildirim olarak taşındığında 976 belirteç ile 32 gidiş-dönüş eder; bildirim 19 mesaj ve 48 gidiş-dönüş kazandırır. Bedeli, hatta düşen beş bildirimin gönderen tarafta hiçbir iz bırakmamasıdır: aynı kayıp istek-yanıt tasarımında beş eksik yanıt olarak görünür, bildirimde görülen kayıp iki koşumda da sıfırdır.

Önceki üç derste bağlantının **nasıl kurulduğu** ölçüldü: araç bağlantısının bir belirtime
bağlanması, barındırıcı, istemci ve sunucu arasındaki sorumluluk dağılımı, yerel ile uzak aktarımın
gidiş-dönüş farkı. Üçünde de sayılan şey bağlantının kendisiydi. Üzerinden **ne geçtiği** hiç
açılmadı.

Bu ders o boşluğu doldurur. Model bağlam protokolünün **veri katmanı (data layer)** bağlantının
üstünde durur ve yalnız üç mesaj türü tanır: **istek**, **yanıt** ve **bildirim**. Ölçülecek olan
bu üç türün her birinin **kaça mal olduğudur** — kaç mesaj, kaç zarf belirteci, kaç gidiş-dönüş — ve
bunlardan birinin, bildirimin, **yanıtsız** olmasının ne kazandırıp neyi görünmez kıldığıdır.

- **PY31.** Ortam, üç sunucu, araçlar ve zarf sayımı **kurgudur**; gerçek bir sunucu, istemci
  kitaplığı ya da çalışma zamanı çağrılmaz. 60 kurgu abone, üç kurgu sunucu, beş bildirilen araç.
  Tohum **20260218**, ikinci koşum **20260219**.
- **PY32.** Üç mesaj türü vardır ve her mesaj bir **zarf** taşır. Zarfın sabit bedeli **8
  belirteçtir**; gövde, alan adlarının ve değerlerin kurgu belirteçleyiciden geçmiş hâlidir.
- **PY33.** Bir **istek** yanıt bekler ve bir gidiş-dönüş harcar: yerel aktarımda bir, uzak
  aktarımda iki. **Bildirim** yanıt beklemez ve sayaçta gidiş-dönüş harcamaz.
- **PY34.** **Yanıt** kendi başına gönderilmez, bir isteğin karşılığıdır; sayaçta ayrı bir tür
  olarak durur çünkü zarfı ayrıca ödenir.
- **PY35.** **Protokolsüz taban** budur: araç ders içinde tanımlıdır, çağrı doğrudan bir işlev
  çağrısıdır, mesaj yoktur, zarf sayılmaz.
- **PY36.** Ölçülen toplu iş sekiz kurgu abonenin dönem bedelidir; her abone `sayac_oku`,
  `tuketim` ve `tarife` sırasından geçer.
- **PY37.** Kurgu aktarım hattı mesajların bir payını düşürür. Kayıp payı **0,20** alınmıştır ve
  sayının görünür olması için yüksek tutulmuştur; düşme kararı tohumla belirlenir.

## Üç Mesaj Türü

İstek ile bildirim arasındaki fark bir biçim farkı değildir, bir **beklenti** farkıdır. İstek
gönderen taraf karşılığında bir yanıt bekler; o yanıt gelene kadar iş yarımdır ve bekleyen taraf
gidiş-dönüşü öder. Bildirim gönderen taraf hiçbir şey beklemez: mesaj hatta bırakılır ve iş devam
eder. Yanıt bu ikisinin arasında bağımsız bir tür değildir — kendi başına gönderilmez, ama zarfı
ayrıca ödendiği için sayaçta ayrı durur.

Web API Tasarımı kursunda bir arayüzün sözleşmesi, sürümlenmesi ve hata yanıtı ölçülmüştü; o yordam
burada tekrarlanmaz. Bu derste sözleşmenin **içeriği** değil, **taşınma bedeli** sayılır: aynı iş
kaç mesaja bölünüyor ve her bölünme kaç belirteç ekliyor. Aşağıdaki kod kursun kurgu ortamını, üç
sunucusunu ve zarf sayacını kurar.

```python
TOHUM, M32 = 20260218, 0xFFFFFFFF


def uretec(t):
    x = ((t ^ (t >> 16)) * 2246822507) & M32
    x = ((x ^ (x >> 13)) * 3266489909) & M32
    s = [(x ^ (x >> 16)) & M32]

    def sonraki():
        s[0] = (s[0] * 1664525 + 1013904223) & M32
        return s[0] / 4294967296
    return sonraki


def belirtecle(m):
    b = []
    for s in str(m).lower().replace(",", " , ").split():
        while len(s) > 5:
            b.append(s[:5])
            s = s[5:]
        b.append(s)
    return b


# ---- KURGU ortam ve araclar (M28/K05 ile ayni kurgu, burada sunucuya tasiniyor)
BOLGE = ["dogu", "bati", "kuzey", "guney", "merkez"]
TIP = ["mesken", "isyeri"]
ABONE = {}
for i in range(60):
    r = uretec(TOHUM + 31 * i)
    onceki = 10000 + int(r() * 80000)
    ABONE[f"A{i + 1:03d}"] = {"bolge": BOLGE[int(r() * 5)], "tip": TIP[int(r() * 2)],
                              "onceki": onceki, "simdiki": onceki + int(r() * 70)}
BASAMAK, USTU, ISYERI_KAT = ((10, 4), (25, 7), (40, 11)), 16, 2


def _bedel(m3, tip):
    kalan, alt, top = m3, 0, 0
    for ust, birim in BASAMAK:
        dilim = min(kalan, ust - alt)
        if dilim <= 0:
            break
        top += dilim * birim
        kalan -= dilim
        alt = ust
    return (top + kalan * USTU) * (ISYERI_KAT if tip == "isyeri" else 1)


def t_sayac(abone=None, **_):
    a = ABONE.get(abone)
    return {"hata": "abone yok"} if a is None else {
        "onceki": a["onceki"], "simdiki": a["simdiki"], "tip": a["tip"]}


def t_tuketim(onceki=None, simdiki=None, **_):
    if onceki is None or simdiki is None:
        return {"hata": "eksik alan"}
    f = simdiki - onceki
    return {"m3": f + 100000 if f < 0 else f}


def t_tarife(m3=None, tip="mesken", **_):
    return {"hata": "eksik alan"} if m3 is None else {"tutar": _bedel(m3, tip)}


def t_bolge(bolge=None, **_):
    if bolge not in BOLGE:
        return {"hata": "bolge yok"}
    n = sum(1 for a in ABONE.values() if a["bolge"] == bolge)
    return {"bolge": bolge, "abone": n}


def t_kayit(abone=None, sutun=None, deger=None, **_):
    if not (abone and sutun and deger is not None):
        return {"hata": "eksik alan"}
    return {"yazildi": True}


# ---- KURGU sunucular: her biri yetenek bildirir
SUNUCU = {
    "olcum": {"surum": 2, "aktarim": "yerel",
              "arac": {"sayac_oku": {"islev": t_sayac, "alan": ("abone",), "yan_etki": False},
                       "tuketim": {"islev": t_tuketim, "alan": ("onceki", "simdiki"),
                                   "yan_etki": False}},
              "kaynak": ("abone_listesi",), "istem": ()},
    "tarife": {"surum": 1, "aktarim": "uzak",
               "arac": {"tarife": {"islev": t_tarife, "alan": ("m3", "tip"), "yan_etki": False}},
               "kaynak": ("basamak_tablosu",), "istem": ("bedel_aciklamasi",)},
    "kayit": {"surum": 3, "aktarim": "uzak",
              "arac": {"bolge_ozet": {"islev": t_bolge, "alan": ("bolge",), "yan_etki": False},
                       "kayit_yaz": {"islev": t_kayit, "alan": ("abone", "sutun", "deger"),
                                     "yan_etki": True}},
              "kaynak": (), "istem": ()},
}
ISTEMCI_SURUM = {"olcum": 2, "tarife": 1, "kayit": 2}      # kayit sunucusu ileride
IZIN = ("sayac_oku", "tuketim", "tarife", "bolge_ozet")     # kayit_yaz izin listesinde yok

SAYIM = {"istek": 0, "yanit": 0, "bildirim": 0, "belirtec": 0, "gidis_donus": 0}


def mesaj(tur, govde, aktarim="yerel"):
    """KURGU zarf. Gercek bir protokol uygulanmaz; sayilan sey zarfin bedelidir."""
    SAYIM[tur] += 1
    b = len(belirtecle(govde)) + 8                       # zarf sabiti
    SAYIM["belirtec"] += b
    if tur == "istek":
        SAYIM["gidis_donus"] += 2 if aktarim == "uzak" else 1
    return b


def elsikismasi(istemci_surum=None, izin=None):
    """Yetenek uzlasmasi: surum uyusmazligi ve izin listesi arac kumesini daraltir."""
    istemci_surum = ISTEMCI_SURUM if istemci_surum is None else istemci_surum
    izin = IZIN if izin is None else izin
    anlasilan, dusen = {}, []
    for ad, s in SUNUCU.items():
        mesaj("istek", f"yetenek sor {ad}", s["aktarim"])
        mesaj("yanit", f"yetenek bildir {ad} surum {s['surum']} "
                       + " ".join(s["arac"]) + " " + " ".join(s["kaynak"]))
        if istemci_surum.get(ad, 0) < s["surum"]:
            dusen.append((ad, "surum", s["surum"], istemci_surum.get(ad, 0)))
            continue
        for t, tan in s["arac"].items():
            if t not in izin:
                dusen.append((ad, "izin", t, None))
                continue
            anlasilan[t] = dict(tan, sunucu=ad, aktarim=s["aktarim"])
    return anlasilan, dusen


def cagir(anlasilan, ad, durum):
    if ad not in anlasilan:
        return {"hata": "arac bildirilmedi"}
    t = anlasilan[ad]
    kw = {a: durum[a] for a in t["alan"] if a in durum}
    mesaj("istek", f"{ad} " + " ".join(f"{k} {v}" for k, v in kw.items()), t["aktarim"])
    s = t["islev"](**kw)
    mesaj("yanit", " ".join(f"{k} {v}" for k, v in s.items()))
    return s


anlasilan, dusen = elsikismasi()
print("anlasilan arac :", " ".join(sorted(anlasilan)))
print("el sikismasi   :", SAYIM["istek"], "istek,", SAYIM["yanit"], "yanit,",
      SAYIM["belirtec"], "belirtec,", SAYIM["gidis_donus"], "gidis-donus")
```

```
anlasilan arac : sayac_oku tarife tuketim
el sikismasi   : 3 istek, 3 yanit, 99 belirtec, 5 gidis-donus
```

## Zarfın Bedeli

Zarf sayacı türe göre saymayı biliyor ama gövde ile zarfı ayırmıyor. Ölçüm için mesajın çevresine
ince bir sargı konur: sargı türü ve gövde belirtecini kendi dökümüne yazar, sonra işi asıl sayaca
devreder. Sekiz abonelik toplu iş bu dökümle koşturulur.

```python
TOPLU = ("A003", "A011", "A017", "A024", "A038", "A045", "A052", "A059")

# ---- olcum sargisi: ayni zarf sayacinin uzerine tur basina govde belirteci
DOKUM = {t: [0, 0] for t in ("istek", "yanit", "bildirim")}
_zarf = mesaj


def mesaj(tur, govde, aktarim="yerel"):
    DOKUM[tur][0] += 1
    DOKUM[tur][1] += len(belirtecle(govde))
    return _zarf(tur, govde, aktarim)


def sifirla():
    for k in SAYIM:
        SAYIM[k] = 0
    for t in DOKUM:
        DOKUM[t] = [0, 0]


def zincir(anlasilan, abone, ilerleme=None):
    """Uc araclik zincir; her adimdan sonra istege bagli bir ilerleme mesaji."""
    durum = {"abone": abone}
    for ad in ("sayac_oku", "tuketim", "tarife"):
        s = cagir(anlasilan, ad, durum)
        durum.update({k: v for k, v in s.items() if k != "hata"})
        if ilerleme is not None:
            ilerleme(abone, ad)
    return durum.get("tutar")


anlasilan, _ = elsikismasi()
sifirla()
print("sekiz abonelik toplu is, tutarlar:", [zincir(anlasilan, a) for a in TOPLU])
print("tur       sayi  govde  zarf  toplam")
for t in DOKUM:
    n, g = DOKUM[t]
    print(f"{t:<9} {n:>4} {g:>6} {n * 8:>5} {g + n * 8:>7}")
print(f"protokollu    : {sum(DOKUM[t][0] for t in DOKUM)} mesaj,"
      f" {SAYIM['belirtec']} belirtec, {SAYIM['gidis_donus']} gidis-donus")
print("protokolsuz   : 24 islev cagrisi, 0 mesaj, 0 zarf belirteci, 0 gidis-donus")
```

```
sekiz abonelik toplu is, tutarlar: [211, 16, 844, 710, 812, 876, 694, 470]
tur       sayi  govde  zarf  toplam
istek       24    152   192     344
yanit       24    104   192     296
bildirim     0      0     0       0
protokollu    : 48 mesaj, 640 belirtec, 32 gidis-donus
protokolsuz   : 24 islev cagrisi, 0 mesaj, 0 zarf belirteci, 0 gidis-donus
```

Son iki satır dersin ilk sayısıdır. Aynı sekiz tutar protokolsüz kurulumda **24 işlev çağrısıyla**
çıkıyor: mesaj yok, zarf yok, gidiş-dönüş yok. Protokollü kurulumda aynı iş **48 mesaja** bölünüyor,
**640 belirteç** ve **32 gidiş-dönüş** ediyor. Belirtecin **384'ü** yalnız zarftır — türe göre 24
istekte 192, 24 yanıtta 192 — ve geriye kalan 256 belirteç gövdedir. Zarf, taşınan bilginin **bir
buçuk katı** kadar yer tutuyor.

Bölünmenin şekli de sayıda görünüyor. İstek gövdesi 152 belirteç, yanıt gövdesi 104; istek daha
pahalı çünkü araç adını ve bütün alanları ad ile değer çiftleri hâlinde taşıyor, yanıt yalnız
sonucu taşıyor. Gidiş-dönüş 32'dir, 24 değil: sekiz zincirin ilk adımı yerel `olcum` sunucusuna,
kalan iki adımı uzak sunuculara gidiyor ve uzak istek gidiş-dönüşü ikiye katlıyor. Bildirim satırı
şimdilik sıfırdır; üçüncü tür bu toplu işte hiç kullanılmadı.

## Bildirimin Kazandırdığı

Toplu iş uzun sürerse çağıran tarafın nerede olduğunu bilmesi istenir. Bu bilgi iki tasarımla
taşınabilir. Birincisinde her adım sonunda bir **istek** gönderilir ve karşı taraf onaylayan bir
yanıt döndürür. İkincisinde aynı metin bir **bildirim** olarak gönderilir ve yanıt beklenmez. İki
tasarım aynı kurgu hat üzerinde, aynı tohumla, aynı düşme kararlarıyla koşturulur.

```python
KAYIP_PAYI = 0.20                    # KURGU hatta ulasmayan mesaj payi


def hat(tohum):
    """KURGU aktarim hatti: mesajlarin bir payi karsi tarafa ulasmaz."""
    r = uretec(tohum)

    def ulasti():
        return r() >= KAYIP_PAYI
    return ulasti


def ilerleme_olc(bicim, tohum=TOHUM):
    """Ayni ilerleme bilgisi iki tasarimda: istek-yanit ciftiyle ya da bildirimle."""
    ulasti, ulasan = hat(tohum), [0]

    def bildir(abone, ad):
        g = f"ilerleme {abone} {ad} tamam"
        if bicim == "istek-yanit":
            mesaj("istek", g, "uzak")
            if ulasti():
                ulasan[0] += 1
                mesaj("yanit", "onay")
        elif bicim == "bildirim":
            mesaj("bildirim", g, "uzak")
            if ulasti():
                ulasan[0] += 1

    anlasilan, _ = elsikismasi()
    sifirla()
    for a in TOPLU:
        zincir(anlasilan, a, bildir)
    gonderilen = 0 if bicim == "yok" else 24
    gorulen = gonderilen - ulasan[0] if bicim == "istek-yanit" else 0
    return (DOKUM["istek"][0], DOKUM["yanit"][0], DOKUM["bildirim"][0], SAYIM["belirtec"],
            SAYIM["gidis_donus"], gonderilen, ulasan[0], gorulen)


print("ilerleme tasarimi istek yanit bildirim belirtec gidis-donus"
      " gonderilen ulasan gorulen")
for b in ("yok", "istek-yanit", "bildirim"):
    for t in (TOHUM, TOHUM + 1):
        s = ilerleme_olc(b, t)
        print(f"{b:<15} {'AB'[t - TOHUM]}  {s[0]:>5} {s[1]:>5} {s[2]:>8} {s[3]:>8}"
              f" {s[4]:>11} {s[5]:>10} {s[6]:>6} {s[7]:>7}")
```

```
ilerleme tasarimi istek yanit bildirim belirtec gidis-donus gonderilen ulasan gorulen
yok             A     24    24        0      640          32          0      0       0
yok             B     24    24        0      640          32          0      0       0
istek-yanit     A     48    43        0     1147          80         24     19       5
istek-yanit     B     48    44        0     1156          80         24     20       4
bildirim        A     24    24       24      976          32         24     19       0
bildirim        B     24    24       24      976          32         24     20       0
```

İlk iki satır ilerlemesiz tabandır ve iki koşumda da aynıdır. İlk koşumda istek-yanıt tasarımı
toplu işin mesaj sayısını 48'den **91'e**, belirteci 640'tan **1147'ye**, gidiş-dönüşü 32'den
**80'e** çıkarıyor. Bildirim tasarımı aynı bilgiyi **72 mesaj**, **976 belirteç** ve **32
gidiş-dönüşle** taşıyor. Bildirimin kazancı üç sütunda birden okunur: **19 mesaj**, **171
belirteç** ve **48 gidiş-dönüş**.

Üç sayının kaynağı ayrıdır. Mesaj kazancı ulaşan isteklerin yanıtlarıdır; ilk koşumda 19 istek
ulaştı, 19 onay döndü ve bildirim tasarımında bu 19 onay hiç yazılmadı. Belirteç kazancı bu 19
yanıtın zarfı ile gövdesidir, mesaj başına dokuz belirteç. Gidiş-dönüş kazancı en büyüğüdür ve
ulaşma ile hiç ilgisi yoktur: 24 ilerleme mesajının hepsi uzak aktarımdan geçtiği için istek
tasarımında **her biri iki gidiş-dönüş** harcadı, bildirimde **hiçbiri harcamadı**. Bekleyen bir
taraf olmadığında hat üzerinde beklenen bir şey de yoktur.

## Bildirimin Görünmez Kıldığı

Aynı tablonun son üç sütunu bedeli taşır. Kurgu hat ilk koşumda 24 ilerleme mesajının **19'unu**
geçirdi, ikinci koşumda **20'sini**. İstek-yanıt tasarımında gönderen tarafın gördüğü kayıp bu
farkın tamamıdır: ilk koşumda **5**, ikinci koşumda **4**. Bildirim tasarımında aynı hat, aynı
tohum ve aynı düşme kararlarıyla aynı sayıda mesaj kayboldu, ama gönderenin gördüğü kayıp iki
koşumda da **sıfırdır**.

Fark yanıtın kendisinden gelir. Kayıp bir istekte beklenen yanıt gelmez ve beklemenin sona ermesi
gönderen tarafta bir olaydır — sayılabilir, günlüğe yazılabilir, yeniden denenebilir. Kayıp bir
bildirimde beklenen bir şey yoktur; gönderen sayacı 24 der, alan tarafın sayacı 19 der ve aradaki
beş mesaj **hiçbir yerde hata üretmez**. İki sayacı yan yana koymayan bir kurulumda bu fark
görünmez.

Buradan çıkan kural mesaj türü seçimini belirler. Karşı tarafın **davranmak zorunda olduğu** ve
gönderenin sonucunu **bilmek zorunda olduğu** hiçbir bilgi bildirimle taşınmaz: araç çağrısı,
yetenek sorgusu, yazma işlemi. Kaybı işi bozmayan bilgi ise bildirime uygundur: ilerleme, günlük
satırı, durum değişikliği duyurusu. İki koşumun farkı da bu ayrımı doğruluyor — kayıp sayısı
koşumdan koşuma 5 ile 4 arasında oynuyor, ama bildirim tasarımında **görülen** kayıp iki koşumda da
sıfır kalıyor. Değişen şey kayıptır, değişmeyen şey körlüktür.

## Özet

- Veri katmanı üç mesaj türü tanır: istek yanıt bekler ve gidiş-dönüş harcar, yanıt bir isteğin
  karşılığıdır, bildirim yanıt beklemez ve sayaçta gidiş-dönüş harcamaz.
- Sekiz abonelik toplu iş protokolsüz kurulumda 24 işlev çağrısı, sıfır mesaj ve sıfır zarf
  belirteciyken protokollü kurulumda 48 mesaj, 640 belirteç ve 32 gidiş-dönüştür.
- 640 belirtecin 384'ü zarftır ve taşınan 256 belirteçlik gövdenin bir buçuk katı yer tutar.
- Aynı ilerleme bilgisi ilk koşumda istek-yanıt çiftiyle 91 mesaj, 1147 belirteç ve 80 gidiş-dönüş;
  bildirimle 72 mesaj, 976 belirteç ve 32 gidiş-dönüş eder. Bildirimin kazancı 19 mesaj, 171
  belirteç ve 48 gidiş-dönüştür.
- Kurgu hat iki koşumda 5 ve 4 mesaj düşürdü; istek-yanıt tasarımında gönderen bu kaybın tamamını
  gördü, bildirim tasarımında iki koşumda da sıfırını gördü.
- Karşı tarafın davranmak zorunda olduğu ve sonucu bilinmesi gereken hiçbir bilgi bildirimle
  taşınmaz; bildirim yalnız kaybı işi bozmayan bilgiye uygundur.

## Sonraki Adım

Bu derste mesajların bedeli sayıldı, ama sayılan mesajların hepsi **anlaşılmış** bir araç kümesi
üzerinde çalıştı. İlk bloğun çıktısındaki tek satır bunu sessizce ele veriyor: el sıkışmasından üç
araç çıktı, oysa üç kurgu sunucunun bildirdiği araç sayısı daha fazladır. Sunucunun ne bildirdiği,
istemcinin bunun ne kadarını aldığı ve aradaki farkın **hangi mesajda hangi hatayla** oluştuğu hiç
sorulmadı. Sonraki ders sunucu yeteneklerini — araç, kaynak ve istem — bildirilen ile anlaşılan
arasındaki farkla ölçer ve o farkın hiçbir hata mesajı üretmeden nasıl oluştuğunu sayar.
