İçindekiler
- 1 Hiç tablo değiştirirken terlediğiniz oldu mu?
- 2 Şema değişikliği neden can yakar? Küçük bir aynaya bakış
- 3 Blue/Green: Değişikliği güvenli bir oyun alanında büyütmek
- 4 pt-online-schema-change: Tetikleyicilerle yumuşak dosdoğru adımlar
- 5 gh-ost: Binlog’u dinleyip gölgeyle dans eden usta
- 6 Peki Blue/Green ile ikisini nasıl sahneye çıkarırım?
- 7 Ufak ama kritik püfler: Geri dönüş, fren pedalı ve nabız
- 8 Gerçek bir senaryo: Sipariş tablosuna sütun eklerken tansiyonu düşürmek
- 9 Sık düşülen çukurlar: Küçük uyarılar büyük rahatlık
- 10 Gözün arkada kalmasın: Doğrulama ve görünürlük
- 11 Kapanış: Şemayı büyütürken kalbi yormamak
Hiç tablo değiştirirken terlediğiniz oldu mu?
Bir öğle arasında, müşteri hizmetlerinden gelen bir notla başlayan o meşhur günlerden biriydi. “Sipariş listesinde teslimat zamanını göremiyoruz, acil bir sütun ekleyebilir miyiz?” Basit duruyor, değil mi? Ben de bir zamanlar “Hemen ALTER atalım, ne olacak ki?” diyenlerdendim. Sonra üretimde kilitlenen bir tablo, artan yanıt süreleri ve telefonla arayan ekip arkadaşları… İşte o an anladım: Veritabanı şema değişikliği, trafiğin tam ortasında şerit değiştirmeye benziyor. Aynaya bakmadan olmaz.
Bu yazıda, MySQL’de sıfır kesinti şema değişiklikleri için iki sihirli anahtardan bahsedeceğim: pt-online-schema-change ve gh-ost. İkisini de yıllardır farklı trafik desenlerinde, farklı acılar çekerek deneyimledim. Ayrıca bu değişiklikleri daha güvenli hale getiren Blue/Green stratejisini adım adım anlatacağım. Mesela şöyle düşünün: Canlı ortam (Blue) trafiği alırken, yeni şemayı Green’de hazırlıyor, beğenirseniz düğmeye basıp trafiği oraya kaydırıyorsunuz. Bu sayede kesinti yaşatmadan, tedirginlik seviyesini düşürerek ilerliyorsunuz. Hazırsanız, yola sakin sakin çıkalım.
Şema değişikliği neden can yakar? Küçük bir aynaya bakış
MySQL’de klasik bir ALTER, tabloyu anlık da olsa kilitleyebilir. Küçük bir tabloda göz bile kırpmazsınız, ama trafik yüksekse o tek göz kırpma birden bire sayfaların geç gelmesine dönüşür. Üstelik iş yalnızca kilitle değil; uzun süren işlemler, arka planda artan sorgu kuyrukları ve uygulama tarafında zaman aşımı olarak geri döner. Bir de bu işler genellikle “küçük bir ekleme” niyetiyle başlar, sonra geceye sarkar.
Benim için kırılma noktası, “Bu işi trafik akarken nasıl yumuşatırız?” sorusu oldu. Cevap, veriyi bir gölge tabloda kopyalarken canlı akışı yakından izlemekten geçiyor. pt-online-schema-change ve gh-ost tam burada devreye giriyor. Biri tabloya tetikleyici koyup değişen satırları yeni tabloya taşırken, diğeri binlog akışını dinleyerek hareket ediyor. Mekanikler farklı ama hedef aynı: Kullanıcıların fark etmeyeceği kadar sarsıntısız bir geçiş.
Blue/Green: Değişikliği güvenli bir oyun alanında büyütmek
Blue/Green’i bir mutfak ve servis benzetmesiyle anlatmayı seviyorum. Blue, hâlihazırda servis veren mutfak. Green ise yeni menüyü hazırladığınız test tezgahı. Green’de yemeği pişirir, tadına bakar, masalara akacak şekilde son dokunuşları yaparsınız. Sonra tek bir hamleyle servis kapısını Green’e açarsınız. MySQL tarafında bu, genellikle ayrı bir kopyada (replica ya da yeni bir düğüm) şemayı büyütmek, index eklemek, sütunları düzenlemek ve veri uyumunu test etmek demek.
Bu yaklaşımın en sevdiğim yanı, geri dönüş yolunun hep açık olması. Bir şey hoşunuza gitmezse, Blue orada duruyor. Trafiği hemen geri alırsınız. Büyük değişikliklerde ve özellikle yoğun saatlerde, bu zihinsel güvenlik ağı ekipteki tansiyonu ciddi düşürüyor. Tek dikkat noktası, Blue ile Green’in veride ayrışmamasını sağlamak. Bu yüzden replikasyonun sağlıklı olduğundan emin olmanız, kesim anında da hızlı bir doğrulama yapmanız şart.
pt-online-schema-change: Tetikleyicilerle yumuşak dosdoğru adımlar
İlk göz ağrılarımdan biri pt-online-schema-change. Onu bir veri marangozu gibi düşünebiliriz: Eski masanın yanına yeni bir masa kuruyor, tahtaları tek tek taşıyor, bu sırada masaya gelen yeni kırıntıları da unutmuyor. Nasıl? Tabloya tetikleyiciler ekleyerek, canlı yazılan her şeyi yeni tabloya da işler. Ardından küçük parçalara bölerek mevcut satırları taşır. Sonunda şık bir isim değişikliğiyle yeni tabloyu eskisinin yerine koyar.
Komut olarak genellikle şu tatta çağırıyorum. Aşırı teknik olmadan, hissiyat vermek için bir örnek:
pt-online-schema-change --alter "ADD COLUMN delivered_at DATETIME NULL" D=mydb,t=orders --execute --max-load Threads_running=20 --critical-load Threads_running=50 --chunk-time 0.5 --statistics
Burada chunk-time ile taşıma hızını nefes nefese olmayacak şekilde ayarlar, max-load ile de veritabanı yorulduğunda frene basmasını söylerim. Tetikleyiciler sayesinde canlı yazılar yeni tabloya da düşer, böylece geride veri kalmaz. Güzel yanı, uygulama fark etmeden arka planda taşımanın sürmesidir. Dezavantaj dediğim kısım ise tetikleyici yükü. Trafiğiniz çok yoğun ve kritikse, tetikleyicilerin yarattığı ekstra dokunuşu hesaba katmak gerekir. Bir de, tabloda zaten tetikleyiciler varsa ayrı bir özen ister.
Şunu da ekleyeyim: Yabancı anahtarlar, büyük metin alanları ve devasa index değişiklikleri sırasında sabırlı olmakta fayda var. Ufak bir kuru prova için ben her zaman staging’de kısa bir tablo kopyasıyla deneme yaparım. Taşımanın ritmini orada bulur, canlıya öyle geçerim. Belgeleri okurken özellikle pt-online-schema-change belgeleri içindeki uyarıları gözlerim; yıllar içinde iyi püf noktaları birikti.
gh-ost: Binlog’u dinleyip gölgeyle dans eden usta
gh-ost ile ilk tanıştığımda hissettiğim şey şuydu: “Bu araç, kalabalığın ritmini dinleyip ona göre adım atıyor.” Tetikleyici yerine binlog akışını izleyerek değişiklikleri yakalıyor. Canlı tabloya yazılan her yeni kayıt veya güncelleme, binlog’dan okunup gölge tabloya işleniyor. Böylece uygulama sorgularına fazladan tetikleyici yükü bindirmeden ilerleyebiliyorsunuz. Trafiğin temposuna kulak verip, gerekirse kendini yavaşlatabiliyor.
Benim sık kullandığım yalın bir çağrı örneği şöyle:
gh-ost --host=db-primary --database=mydb --table=orders
--alter="ADD COLUMN delivered_at DATETIME NULL"
--cut-over=default --max-lag-millis=1500 --execute
Burada max-lag-millis ile replikasyon gecikmesine saygı duymasını, cut-over ile de kesim anını nasıl yöneteceğini belirliyorsunuz. Binlog bazlı ilerlediği için özellikle RBR (row-based) biçimini seviyor; ortamınızda bu ayarı kontrol etmek iyi bir fikir. Ben genellikle gh-ost deposundaki kullanım örnekleri ve notlar arasından senaryoma en yakın bayrakları seçerim. Şunu da unutmayın: gh-ost, etkisini zeki bir şeklide yayar ama tamamen görünmez değil. Büyük koltukları bir odadan diğerine taşırken çıkardığınız küçük sesler gibi, sistemde izlerini görürsünüz; bu normal.
Peki Blue/Green ile ikisini nasıl sahneye çıkarırım?
En sevdiğim kurgu şöyle işliyor. Önce Green tarafını ayarlıyorum: Taze bir kopya, Blue’yu huzurla takip ediyor. Bu bir replica olabilir ya da yeni bir düğüm. Sonra Green’de şema değişikliğini çalıştırıyorum. Eğer Green, Blue’dan replike oluyorsa ve ben gh-ost kullanıyorsam, Green’in kendi üzerinde gölge tabloyu büyütürken Blue’nun akışını da binlog ile yakalıyorum. pt-online-schema-change tercih ediyorsam, Green’de tetikleyicilerle taşıma yapıyorum. İkisi de bittiğinde, Green’in verisini hızlıca kokluyorum: Satır sayıları tutuyor mu, kritik raporlar makul mü, sorgu planı uçmuş mu?
Sonra geliyor “kesim anı”. Burada bir anda tozu dumana katmaya gerek yok. Uygulamanın veritabanına bağlandığı yeri tek bir hamleyle Green’e çeviriyorum. Bunu yapan bir bağlantı katmanı varsa işiniz kolay; yoksa uygulamayı ufak bir konfigürasyon değişikliğiyle yeni düğüme yönlendirmek de olur. DNS ile yapanları da gördüm, ama ben genellikle kısa yaşayan bağlantıların olduğu bir uygulamada, bağlantı havuzu ayarını güncellemeyi tercih ediyorum. Şu kadarını söyleyeyim: Hazırlık iyi ise, kesim ânı tek bir nefes gibi geçiyor.
Green’den memnunsanız, bir süre Blue’yu da hayatta tutup can yeleği gibi üzerinizde taşıyın. Hani olur da bir raporda beklenmedik bir sapma yakalarsınız, geriye dönüşünüz net olsun. Bu kısa “gözlem süresi”, ekibin omuzlarını indiriyor.
Ufak ama kritik püfler: Geri dönüş, fren pedalı ve nabız
Ne yapıyorsanız yapın, geri dönüşünüzü daha ilk dakikada tasarlayın. pt-online-schema-change, kesimden önce eski tabloyu güvenle kenara alır. gh-ost da benzer şekilde “eski kapıyı” hemen kırmaz. Yani problem hissederseniz tek bir adımla eski hâle dönebilmeli ve bunu daha önceden prova etmiş olmalısınız. Ben pratikte şu yaklaşımı seviyorum: Kesimden sonra belirlediğiniz kısa zaman penceresinde, en kritik kullanımları hızlıca test eden küçük bir kontrol listesi çalıştırın. Ödeme akışı, rapor sayfası, admin panelde bir arama… Üç beş dakika bile paha biçilemez.
İkinci konu, fren pedalı. Her iki araçta da “çok hızlandım, nefesleneyim” diyebileceğiniz bayraklar var. pt-online-schema-change için –max-load, –critical-load gibi; gh-ost için –max-lag-millis gibi. Bunlar birer güvenlik kemeri. Trafik artınca araca “dur, sıkışıyoruz” demenizi sağlar. Üçüncü konu ise nabız: Uygulama tepkileri, sorgu süreleri, veritabanı bekleme süreleri. Eğer merkezi izlemeniz yoksa, yola çıkmadan önce küçük bir pano kurun. Canlı ortamlarda, basit grafikleri bile sevgiyle anarsınız.
Yüksek erişilebilirlik konularını kurcalarken, MariaDB Galera ve MySQL Group Replication ile kesintisizliğe sıcak bir yolculuk yazımda anlattığım fikirlerin burada çok işe yaradığını gördüm. Oradaki düşünce, düğümler arası güvenli geçişi mümkün kılıyor; burada da aynı rahatlığı midenizde hissediyorsunuz.
Gerçek bir senaryo: Sipariş tablosuna sütun eklerken tansiyonu düşürmek
Gelin en baştaki hikâyeyi toparlayalım. “orders” tablosuna delivered_at sütunu eklenecek. Trafik gündüz yoğun, gece nispeten sakin. Ekip olarak bir Green kopya hazırlıyoruz. Bu kopya, Blue’yu takip eden bir replica. Replikasyonun sağlıklı olduğunu gördükten sonra, Green’de gh-ost’u çalıştırıyorum. Bayraklar ölçülü, replikasyon gecikmesine saygılı bir ayar. Bu arada uygulama Blue’dan yazmaya devam ediyor. gh-ost, binlog akışını dinleyerek yeni sütunu olan gölge tabloyu besliyor.
Taşıma tamamlanınca Green’de hızlı bir kontrol yapıyorum. Kritik sorguların planı fena değil, sayılar tutuyor, raporlar makul. Ekip aynı anda uygulamanın bağlantı ayarını Green’e çeviriyor. Bir iki dakika gözlemlemede kalıyoruz. Beklenmedik bir ağrı yok. Ertesi günün sabahında, Blue’yu da ufak bir temizlikle kapatıyoruz. Buradaki temel kazanım şu: Kimsenin hissetmediği bir operasyonla, düşük riskle yeni bir şemaya geçtik. Bu özgüven bir sonraki değişikliğin kapısını aralıyor.
Sık düşülen çukurlar: Küçük uyarılar büyük rahatlık
Deneyimlerimden birkaç nokta, aklınızın bir kenarında dursun. Tabloda hâlihazırda tetikleyici varsa, pt-online-schema-change ile çakışmalar yaşanabilir; önce dikkatlice okumanız, bazen de farklı bir yöntem seçmeniz gerekebilir. gh-ost için binlog biçiminin uygun olduğundan emin olun; bazı ortamlarda politikalar gereği ayar değişikliği yapamıyorsunuz, o zaman planı sadeleştirmek gerekir. Uzun süren transaction’lar, taşıma sırasında sizi bekletebilir; bu yüzden kampanya döneminde ya da rapor akışlarının yoğun olduğu saatlerde değişikliği başlatmamayı severim.
Bir de “metadata lock” denilen küçük ama etkili can sıkıcı anlar var. Her şey yolunda giderken, masanın kenarına takılan bir ceket gibi bir anda takılabilirsiniz. Prova sırasında bu kilitleri tetikleyen akışları görürseniz, saat seçiminizi değiştirin. MySQL’in çevrimiçi DDL notları gibi rehberler, nereye basarsanız iz çıkacağını kaba hatlarıyla anlatır; okuyup içinizi rahatlatın.
Gözün arkada kalmasın: Doğrulama ve görünürlük
Kesimden önce ve sonra minik bir doğrulama ritüeli oluşturun. Satır sayıları tutuyor mu, kritik sayfalarda tepki normal mi, hata kayıtlarında yeni bir koku var mı? Eğer log’larınız ve grafikleriniz derli topluysa, bu kontrol 5-10 dakikada biter. Yoksa, en azından uygulama hatalarını toplayan küçük bir görünüm işinizi görür. Ben genellikle taşıma süresince birkaç uyarı eşiği kurarım: Sorgu süresi belirli bir eşiği geçerse, replikasyon gecikmesi artarsa ya da bağlantı havuzu aşırı kullanıma giderse haberim olur. Bu küçük sinyaller, operasyon boyunca size arkadaşlık eder.
Bu arada, izleme ve günlükleri düzenlemek istiyorsanız, benzer ruhla yazdığım diğer rehberler size ilham verebilir. Araçların kurulumu ayrı bir dünya ama zihniyet aynı: Sessiz ve sakin bir sürüş için göstergeler şart.
Kapanış: Şemayı büyütürken kalbi yormamak
Veritabanında şema değişikliğini canlıda yapmak, ilk bakışta yutkunmalık gelebilir. Fakat doğru araçlarla ve Blue/Green zihniyetiyle, bunu günlük rutinin bir parçası haline getirmek mümkün. pt-online-schema-change tetikleyicilerle, gh-ost ise binlog’dan beslenerek gölge tabloyu büyütür. İkisiyle de defalarca sakin sakin geçişler yaptım. En çok işime yarayan üç şey hep aynı oldu: Önceden prova, keskin bir geri dönüş planı ve taşıma sırasında sistemi dinleyen ufak bir izleme.
Eğer ilk kez deneyecekseniz, küçük bir tablo ve düşük riskli bir değişiklikle başlayın. Ritmi orada bulun, sonra büyük adımlara geçin. Yolculuğun sonunda en sevdiğim cümleyi duyarsınız: “Kimse fark etmedi ama büyük bir işi bitirdik.” Umarım bu yazı zihninizde birkaç taşın yerini değiştirir. Sorularınız olursa her zamanki gibi buradayım. Bir sonraki yazıda görüşürüz; şemanız açılsın, kesiminiz sessiz olsun.
