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
-
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.
-
Büyük ve kilitleyici bir
ALTERdeploy 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. -
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ı
-
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.
-
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
UPDATEhem kilitler hem timeout’a sokar. -
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-ostgibi online-DDL araçlarıyla bant dışı çalıştır; tabloyu kilitlemeden kolonu ekler. -
İ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.
Yorumlar
Yorum yapmak için GitHub hesabınızla giriş yapmanız yeterli. Yorumlar GitHub Discussions üzerinde saklanır.