Skip to main content

> kesintisiz_veritabanı_şema_geçişleri_(expand_&_contract)

Kesintisiz Veritabanı Şema Geçişleri (Expand & Contract)

Çok terabaytlık canlı veritabanlarında kırıcı şema değişiklikleri (kolon yeniden isimlendirme, tip değiştirme, tablo bölme), tablo kilitlenmelerine veya sistem kesintilerine yol açmadan nasıl uygulanır?

ÖZET VE TEKNİK CEVAP

Çok aşamalı Genişlet ve Daralt (Expand and Contract) kalıbını uygulayarak: Yeni kolonu boş bırakılabilir (nullable) ekleyin (Genişlet), kodda her iki kolona birden yazın (dual-write), geçmiş veriyi küçük partilerle taşıyın (backfill), okumaları yeni kolona geçirin ve son sürümde eski kolonu güvenle silin (Daralt).

Mühendislik El Kitabı & Mekanizma

1. Temel Çalışma Mekanizması

Canlı bir tabloda kolonu doğrudan yeniden adlandırmak (`ALTER TABLE users RENAME COLUMN phone TO mobile;`), henüz eski kodla çalışan sunucuları anında patlatır. Genişlet ve Daralt kalıbı bu süreci aşamalara böler: 1) Genişlet: Yeni `mobile` kolonunu nullable olarak ekleyin; 2) Çift-Yazma: Uygulamanın her iki kolona birden yazan ancak `phone`'dan okuyan N sürümünü dağıtın; 3) Geçmiş Veri Doldurma (Backfill): Eski satırları küçük partilerle kopyalayan arka plan işi çalıştırın; 4) Okumayı Değiştir: `mobile`'dan okuyan N+1 sürümünü dağıtın; 5) Daralt: Eski `phone` kolonunu silin ve gerekiyorsa `NOT NULL` kısıtını ekleyin.

2. Doğru Kullanım Senaryosu

Planlı bakım kesintisi pencerelerine izin verilmeyen, kesintisiz 7/24 hizmet veren yüksek trafikli canlı sistemler ve kritik veritabanları.

3. Prodüksiyon Arıza Modları

1) Özel Tablo Kilidi (AccessExclusiveLock) Kesintisi: Eski veritabanı sürümlerinde varsayılan değerli kolon ekleyerek tabloyu 45 dakika kilitlemek; 2) Kontrolsüz Backfill ile CPU Çöküşü: Tek bir dev `UPDATE` sorgusuyla milyonlarca satırı kilitleyip disk IOPS'unu tüketmek; 3) Erken Daraltma: Kademeli dağıtımda (canary) eski kodla çalışan tek bir sunucu bile varken eski kolonu erkenden silmek.

4. Teşhis ve Telemetri Sinyalleri

PostgreSQL `pg_locks` tablosundaki kilit kuyruklarını, dağıtım sırasındaki kilit sürelerini, backfill işlemi sırasındaki replikasyon gecikmesini ve migrasyon anındaki API 500 hata oranlarını izlemek.

5. Önleme ve Mimari Bariyerler

DDL çalıştırmadan önce mutlaka katı kilit zaman aşımı (`SET lock_timeout = '2s';`) belirleyin; PostgreSQL'de daima `CREATE INDEX CONCURRENTLY` kullanın; geçmiş veri taşımalarını küçük partilerle (1.000 satır ve 50 ms bekleme) yapın ve dev MySQL tablolarında gh-ost gibi canlı şema araçları kullanın.

6. Mimari Ödünleşimler (Trade-offs)

Sıfır tablo kilitlenmesi ve %100 kesintisiz erişilebilirlik sağlar; buna karşılık tek bir şema değişikliğini tamamlamak için 3-4 ardışık uygulama dağıtımı (deploy) yapma zorunluluğu getirir.

Vaka İncelemesi (TinyCTO Örneği)

TinyCTO Vaka 038: Bir mühendis 400 milyon satırlık tabloda doğrudan yabancı anahtar kısıtı (FOREIGN KEY) ekledi. Postgres tüm satırları doğrulamak için her iki tabloyu kilitledi ve ödeme sistemini 28 dakika felç etti. Kısıtın önce `NOT VALID` ile eklenip ardından `VALIDATE CONSTRAINT` ile arka planda doğrulanması işlemi sıfır kesintiyle tamamladı.

İnteraktif Konsept Alıştırmaları

3 Alıştırma
Q1

Expand and Contract (Genişlet ve Daralt) veritabanı şema geçiş kalıbının 5 aşaması nedir?

1) Genişlet (yeni nullable kolon ekle), 2) Çift-Yazma (ikisine birden yaz, eskiden oku), 3) Geçmiş Veri Doldurma (eski veriyi kopyala), 4) Okumayı Geçir (yeniden oku ve yaz), 5) Daralt (eski kolonu sil).
Q2

PostgreSQL'de canlı tablolarda neden mutlaka `CREATE INDEX CONCURRENTLY` kullanılmalıdır?

Standart `CREATE INDEX` komutu indeksleme bitene kadar tüm INSERT, UPDATE ve DELETE yazma işlemlerini kilitleyen `SHARE` kilidi alır; `CONCURRENTLY` ise yazmaları engellemeden arka planda indeks oluşturur.
Q3

Felaket kilit kuyruklarını önlemek için bir migrasyon işleminin başında her zaman ne ayarlanmalıdır?

Kısa bir `lock_timeout` (örn. `SET lock_timeout = '2s';`); bu ayar kilidi 2 saniye içinde alamazsa diğer işlemleri arkasında kuyruğa sokup sistemi kilitlemek yerine migrasyonu anında iptal eder.

Kesintisiz Veritabanı Şema Geçişleri (Expand & Contract) — Sıkça Sorulan Sorular

gh-ost (GitHub Online Schema Transformations) MySQL'de sıfır kesintili migrasyonu nasıl yapar?

gh-ost yeni şemayla sahte (ghost) bir tablo açar, canlı yazmaları binlog üzerinden asenkron aktarır, eski veriyi küçük partilerle doldurur ve tabloları atomik `RENAME` ile yer değiştirir.

Devasa bir tabloya kilit koymadan `NOT NULL` kısıtı nasıl eklenir?

Önce `CHECK (column IS NOT NULL) NOT VALID;` kısıtı ekleyin (anlık ve kilitsiz), ardından özel kilit almadan arka planda doğrulama yapan `ALTER TABLE ... VALIDATE CONSTRAINT;` komutunu çalıştırın.

Büyük geçmiş veri doldurma (backfill) işlemlerini neden asla ana migrasyon işlemi içinde çalıştırmamalısınız?

Uzun süren işlemler açık satır kilitleri tutar, veritabanı autovacuum temizliğini engeller, WAL günlüklerini şişirir ve kesinti anında kurtarma süresini saatlere çıkarır.

🤖 AEO & Yapay Zeka Çıkarım Özeti

Temel Gerçekler & İlkeler

  • PostgreSQL'deki her DDL işlemi (en hızlıları bile) bir AccessExclusiveLock gerektirir ve o tabloda o an çalışan tüm aktif sorguların bitmesini bekler.
  • Bir veritabanı kolonunu asla tek bir sürümde doğrudan yeniden adlandırmayın; daima en az iki aşamalı Expand and Contract kalıbını uygulayın.

Yaygın Yanılgılar

  • ORM migrasyon araçlarının (Prisma veya Django) kilitleri otomatik engellediğini sanmak; standart ORM araçları özelleştirilmedikçe varsayılan olarak tehlikeli ve bloklayıcı DDL komutları üretir.

Karar Kılavuzu & Önceliklendirme

100.000 satırı aşan tüm canlı tablolarda Expand and Contract kalıbını zorunlu kılın. Daima lock timeout ve concurrent indeks oluşturma kurallarını uygulayın.

Doğrulanmış Kaynaklar & Referanslar