İçeriğe geç
Muhammet Şafak
en
Soran: Melih Cevaplandı:

CI/CD'de veritabanı göçlerini (migrations) güvenli nasıl çalıştırırım?


Soru

CI/CD sürecimizde `php artisan migrate` deployment adımları arasında otomatik çalışıyor. Bir migration çok büyük bir tabloya kolon eklerse ve uzun sürerse pipeline timeout'a düşüyor; ya da o sırada canlıda olan eski kod, DB değişikliği yüzünden hata vermeye başlıyor. Büyük projelerde "backward-compatible migration" prensiplerini CI/CD akışında nasıl uygularım?

Cevap

Kısa cevap: Asıl hata, şema değişikliğini eski kod hâlâ canlıyken deploy’a sıkı sıkıya bağlamak — çözüm, geriye uyumlu (expand/contract) migration’ları kod deploy’undan ayırmak.

Kısa cevap

Problemi netleştirelim: ya eski kod yeni şemayla karşılaşıp patlıyor, ya da büyük bir ALTER tabloyu kilitleyip pipeline’ı timeout’a düşürüyor. İkisi de aynı kökten — kuplaj. Aynı geçişin canlı tablo tarafını, yani veri kaybetmeden dual-write ile şema değiştirmeyi ayrı bir kayıtta ele almıştım; buradaki soru o geçişi CI/CD adımlarına nasıl dağıtacağınız.

Neden

  1. Eski kod yeni şemayı görmek zorunda kalıyor. Deploy sırasında bir süre boyunca canlıda olan kod, henüz kendisi için yazılmamış bir şemayla konuşur; kolonu tanımadığı ya da beklediği kolonu bulamadığı anda hata vermeye başlar.

  2. Büyük ve kilitleyici bir ALTER deploy adımının içine sığmaz. Milyonlarca satırlık bir tabloya kolon eklemek dakikalar sürer; bu iş deploy adımının içindeyse pipeline timeout’a düşer, tablo da o süre boyunca kilitli kalır.

  3. Kök neden kuplaj. Şema değişikliği ile kod deploy’u aynı ana bağlandığı sürece bu iki hata da kaçınılmazdır; çözüm de tek tek semptomları değil, bu bağı gevşetmektir.

Ne yapmalı

  1. Expand/contract disiplinini benimse. Aynı release’de bir kolonu ekleyip onu gerektiren kodu deploy etme; asla rename/drop’u kullanan release ile aynı anda yapma. Önce kolonu nullable ekle, sonra “hem eskiye hem yeniye yazan” kodu deploy et, en son ayrı bir release ile eskiyi kaldır.

  2. Backfill’i request yolundan ve deploy adımından çıkar. Büyük tabloyu doldurma işini ayrı, throttle’lı bir adımda yap — deploy adımının transaction’ı içinde değil. Aksi halde tek bir dev UPDATE hem kilitler hem timeout’a sokar.

  3. Migration’ı kendi pipeline aşaması yap, timeout baskısı olmadan. Şema değişikliğini app deploy’undan ayrı bir stage’e al. Büyük/kilitleyici değişiklikler için pt-online-schema-change / gh-ost gibi online-DDL araçlarıyla bant dışı çalıştır; tabloyu kilitlemeden kolonu ekler.

  4. İdempotent ve geri alınabilir yaz, deploy’u migration’a gate’le. Migration tekrar çalıştığında bozulmasın, geri dönüşü olsun. Deploy’u migration başarısına bağla; ama yıkıcı adımları (drop, rename) yeni kod tamamen yayıldıktan sonraki bir follow-up release’e bırak.

Sonuç: Ben olsam expand/contract’ı kural yapar, migration’ları app deploy’undan ayırır ve büyük/kilitleyici değişiklikleri online araçlarla kritik yolun dışında çalıştırırdım. Şema değişikliğini hiçbir zaman “deploy’un ortasında, eski kod canlıyken” yapma — onu kademeli ve geriye uyumlu yürüt; pipeline timeout’u da, eski kodun patlaması da o zaman ortadan kalkar.

Paylaş:

Yorumlar

Yorum yapmak için GitHub hesabınızla giriş yapmanız yeterli. Yorumlar GitHub Discussions üzerinde saklanır.

Diğer Sorular

Tüm sorular

Sitede Ara

Yazı, proje ve sayfalarda arama yapmak için yazmaya başlayın.

Esc ile kapat Pagefind ile güçlendirildi