Kesintisiz Şema Değişikliği — Genişlet, Taşı, Daralt
Önce şunu oku: MVCC ve Kilitler — Eski Satır Sürümleri Nerede Yaşar?
30 saniyede özet
Yeni sürüm yavaş yavaş yayılırken bir süre eski ve yeni kod aynı tabloya bakar. Bir sütunun adını tek hamlede değiştirmek eski kodu düşürür. Değişikliği küçük, geri alınabilir adımlara bölmek kesintiyi önler.
Bir koridorun adını değiştirmek küçük bir iş gibi görünür. Eski haritayla gelenler için ise değildir.
-
Bayt: Küçük bir iyileştirme yaptım: name sütununun adı artık full_name.
-
Sen: Yeni kodu da aynı anda çıkardın mı?
-
Bayt: Evet! Sürüm yayılırken bir şeyler ters gitti ve geri dönmek de imkânsızdı.
-
Bayt: Koridorun adını değiştirirken eski haritayla gelenleri ne yapacağız?
Küçük bir iyileştirme: name sütununun adı full_name oldu. Yeni sürüm yayılırken bir şeyler ters gitti; üstelik eskisine dönmek de mümkün değildi.
Eski kod ve yeni tablo bir arada
rolling deployUygulama kopyalarını tek tek yeni sürüme geçiren dağıtım. Bir süre eski ve yeni kod aynı veritabanıyla birlikte çalışır.Sözlükte gör →, pod’ları tek tek yeni sürüme geçirir. Bir süre eski ve yeni kod yan yana çalışır. Migration uygulama açılırken (ör. Flyway ile) çalışıyorsa, şema ilk yeni pod’la birlikte değişir; eski pod’lar hâlâ trafik alırken.
Bu yüzden tek bir kural var: her migration, bir önceki kod sürümüyle de çalışmalıdır. Kolon eklemek bu kurala uyar; kolon silmek ya da adını değiştirmek uymaz.
Kafam karıştı, daha basit anlat
Yeni sürüme geçerken bir süre eski ve yeni kod aynı anda çalışır. Tablo ikisine de uymalıdır, yoksa eski kod birden hata vermeye başlar.
Rolling deploy yapılan bir uygulamada, migration yazarken uyulması gereken temel kural hangisi?
Genişlet, taşı, daralt
Kolon adını tek bir ALTER TABLE … RENAME ile değiştirip yeni kodu aynı deploy'da çıkarıyorsun. Deploy sırasında ne olur? Cevabı göster
Eski pod’lar hata verir. İlk yeni pod migration’ı çalıştırdığı anda, hâlâ name kolonunu arayan eski pod’lar “column does not exist” alır. Yeni sürümden eskisine dönmek de imkânsızlaşır.
Adım adım oku
- Sütun tek hamlede yeniden adlandırılırsa, hâlâ çalışan eski pod'lar name sütununu bulamaz ve hata verir.
- Genişlet: yeni full_name sütunu eskisinin yanına eklenir; iki levha yan yana asılır.
- Taşı: yeni kod iki sütuna birden yazar, eski satırlardaki veri yeni sütuna kopyalanır.
- Daralt: bütün pod'lar yeni sürüme geçince eski sütun ayrı bir deploy'da kaldırılır.
genişlet-daraltUyumsuz bir şema değişikliğini, her biri önceki kodla da çalışan adımlara bölmek: yeni yapıyı ekle, veriyi taşı, kodu geçir, eski yapıyı kaldır.Sözlükte gör → değişikliği uyumlu adımlara böler:
- Genişlet: yeni kolonu ekle; kod iki kolona yazar, eskisinden okur.
- Doldur: eski satırları küçük parçalar hâlinde kopyala (backfillYeni eklenen bir kolonu ya da tabloyu mevcut satırlar için geriye dönük doldurmak. Büyük tablolarda küçük parçalar hâlinde yapılır.Sözlükte gör →).
- Okumaları taşı: kod yeni kolondan okur, hâlâ ikisine yazar.
- Daralt: eski kolonu okuyan kod kalmayınca yazmayı bırak, sonra kolonu sil.
Bir bankanın eski transfer tablosunda tutar double olarak saklanmış. Onu numeric’e taşımak, bu dört adımı gerçek bir tabloda izlemek için güzel bir fırsat.
Derinleş · Transfer tutarı: double'dan numeric'e dört adımda 4 dosya · ~69 satır · ilk okumada atlayabilirsin
Kafam karıştı, daha basit anlat
Bir kolonun adını tek hamlede değiştirme. Önce yenisini ekle, veriyi taşı, kod yenisini kullansın. Eskisini en sonda, kimse kullanmadığında sil.
`price` kolonunun tipi integer kuruştan decimal'e geçecek. Kesintisiz yapmak için doğru sıra hangisi?
Her şema değişikliğini, bir önceki kod sürümüyle uyumlu olup olmamasına göre ayır.
Kendin gör
Trafik varken şema değiştirmek
Tohum 363703- pod-1: v1
- pod-2: v1
- pod-3: v1
Oynat ya da adımla.
Şu an ne oldu?
customers.name → customers.full_name
Üç pod rolling update ile güncellenecek. Deploy sırasında eski ve yeni kod aynı veritabanına bakacak.
Görevler0/3
Deploy sırasında eski pod'ların hata vermesine yol açaçık
İpucu
Kolonu tek adımda yeniden adlandır.
Bir index yüzünden sipariş yazmalarını durduraçık
İpucu
Düz CREATE INDEX.
Kolon adını hiçbir isteği düşürmeden ve geri dönüşü açık tutarak değiştiraçık
İpucu
Genişlet, doldur, okumaları taşı, daralt.
Olay günlüğü (0)
Henüz olay yok. Oynat veya adımla.
- Varsayılanla oynat. Tek adımda yeniden adlandırma: eski pod’lar düştü, geri dönüş kapandı.
- Yöntemi “kesintisiz” yap. Dört adım, üç deploy, sıfır hata.
- Değişikliği index yap, “tek adımda”. Yazmalar durdu, istekler timeout aldı.
- “Kesintisiz” seç. Index yazmaları engellemeden oluştu.
Simülatörde tek adımlık yeniden adlandırma sonrası 'geri dönüş kapalı' çıktı. Neden?
Tabloyu kilitleyen değişiklikler
Bazı şema değişiklikleri tabloyu kısa ya da uzun süre kilitler. Büyük tablolarda online karşılıklarını kullan:
| PostgreSQL | SQL Server | Oracle | |
|---|---|---|---|
| Online index | CREATE INDEX CONCURRENTLY | WITH (ONLINE = ON) | CREATE INDEX … ONLINE |
| Not | Transaction bloğu içinde çalışmaz | Sürüme göre değişir (Enterprise, Azure SQL) | Enterprise Edition özelliği |
Kısa kilit alan bir ALTER TABLE bile, uzun bir transaction’ın arkasında beklerken arkasındaki bütün sorguları bekletir. PostgreSQL’de migration’dan önce SET lock_timeout ile beklemeye bir üst sınır koy.
Kafam karıştı, daha basit anlat
Bazı değişiklikler tabloya “bekleyin” tabelası asar. Büyük bir tabloda bu tabela çok uzun kalabilir, bu yüzden tabelasız yapılan online yöntemleri seç.
PostgreSQL'de milisaniyede bitmesi gereken bir `ALTER TABLE orders ADD COLUMN note text` çalıştırıldı ve bütün sipariş sorguları dakikalarca bekledi. Neden?
Bu Flyway migration'ı PostgreSQL'de hata veriyor. Hatalı satır hangisi?
Tuzaklar
Tek dev UPDATE ile doldurmak. Milyonlarca satırı tek transaction’da güncellemek uzun kilitler, şişme ve dev bir geri alma demektir. Parçalara böl.
CONCURRENTLY transaction içinde. Flyway’de o migration’ı transaction dışında çalışacak şekilde ayarla; başarısız olursa geride kalan INVALID index’i temizle.
Daraltmayı unutmak. Yazılmayan ama silinmeyen kolonlar birikir ve bir gün biri onları yeniden kullanır.
Geri alınamaz migration’ı geri dönüşle birlikte düşünmemek. Kolon silindikten sonra eski koda dönmek yalnızca veriyi geri yükleyerek mümkündür.
Yeni full_name kolonunu 50 milyon satır için doldurmak gerekiyor. Hangisi en güvenli yaklaşım?
Kendini sına
Rolling deploy sırasında eski ve yeni kod bir süre aynı veritabanını kullanır.
Beş pod aynı anda açılıyor ve her biri başlangıçta Flyway çalıştırıyor. Aynı migration beş kez mi uygulanır?
Aklında kalacak üç şey
- 1 Yeni sürüm yayılırken eski ve yeni kod aynı veritabanına bakar. Her şema değişikliği bir önceki kod sürümüyle de çalışabilmelidir.
- 2 Ad ve tip değişikliği tek adımda yapılmaz: genişlet, doldur, okumaları taşı, daralt. Her adımda geri dönüş açık kalır.
- 3 Büyük tablolarda kilit alan değişiklikleri online çalıştır (CONCURRENTLY, ONLINE = ON) ve kilit beklemesine bir üst sınır koy.
5 kart sonraki derste seni bekliyor
Bu dersin üstüne kurulanlar
Bunlar bu dersi temel alıyor; hazır olduğunda devam edebilirsin.