1. Göç Mekanizmasının Genel Bakışı
1.1 Göçün Kavramı ve Rolü
Veritabanı göçü, veri modellerindeki değişiklikleri veritabanı yapısıyla senkronize etme sürecidir ve veri kalıcılığı için son derece önemlidir. Uygulama sürümü arttıkça, veri modeli genellikle değişikliklere uğrar, örneğin alan eklenmesi veya silinmesi, indekslerin değiştirilmesi gibi. Göç, geliştiricilerin bu değişiklikleri versiyonlanmış ve sistemli bir şekilde yönetmelerini sağlayarak, veritabanı yapısıyla veri modeli arasında tutarlılığı sağlar.
Modern web geliştirmede, göç mekanizması şu faydaları sağlar:
- Versiyon Kontrolü: Göç dosyaları, veritabanı yapısının değişim geçmişini takip edebilir, her versiyondaki değişiklikleri anlamak ve geri almak kolaylaşır.
- Otomatik Dağıtım: Göç mekanizması sayesinde, veritabanı dağıtımı ve güncellemeleri otomatik hale getirilebilir, manuel müdahalenin olasılığını ve hataların riskini azaltır.
- Ekip İşbirliği: Göç dosyaları, farklı geliştirme ortamlarında ekip üyelerinin senkronize veritabanı yapılarını kullanmalarını sağlar, işbirliğine olanak tanır.
1.2 ent
Çerçevesinin Göç Özellikleri
ent
çerçevesinin göç mekanizması ile entegrasyonu aşağıdaki özellikleri sunar:
-
Bildirimsel Programlama: Geliştiriciler, sadece varlıkların Go temsiline odaklanmaları yeterlidir,
ent
çerçevesi varlıkları veritabanı tablolarına dönüştürme işlemini ele alır. -
Otomatik Göç:
ent
, DDL ifadeleri yazmadan veritabanı tablo yapılarını otomatik olarak oluşturabilir ve güncelleyebilir. -
Esnek Kontrol:
ent
, farklı göç gereksinimlerini desteklemek için çeşitli yapılandırma seçenekleri sunar, örneğin yabancı anahtar kısıtlamalarıyla veya kısa süreli benzersiz kimlik oluşturmayla.
2. Otomatik Göçe Giriş
2.1 Otomatik Göçün Temel Prensipleri
ent
çerçevesinin otomatik göç özelliği, veritabanı yapısını oluşturmak için genellikle ent/schema
dizininde bulunan şema tanım dosyalarına dayanır. Geliştiriciler varlıkları ve ilişkileri tanımladıktan sonra, ent
mevcut yapıyı inceleyecek ve tablolar oluşturmak, sütun eklemek veya değiştirmek, indeksler oluşturmak vb. için ilgili işlemleri otomatik olarak oluşturacaktır.
Ayrıca, ent
'in otomatik göç prensibi "ekleme modunda" çalışır: varsayılan olarak sadece yeni tablolar, yeni indeksler ekler veya tablolara sütun ekler, mevcut tabloları veya sütunları silmez. Bu tasarım, kazara veri kaybını önlemek için faydalıdır ve veritabanı yapısını ileriye dönük olarak kolayca genişletmek sağlar.
2.2 Otomatik Göçü Kullanma
ent
otomatik göçünü kullanmak için temel adımlar aşağıdaki gibidir:
package main
import (
"context"
"log"
"ent"
)
func main() {
client, err := ent.Open("mysql", "root:pass@tcp(localhost:3306)/test")
if err != nil {
log.Fatalf("MySQL'e bağlanılamadı: %v", err)
}
defer client.Close()
ctx := context.Background()
// Otomatik göçü gerçekleştirerek veritabanı şemasını oluştur veya güncelle
if err := client.Schema.Create(ctx); err != nil {
log.Fatalf("Veritabanı şeması oluşturulamadı: %v", err)
}
}
Yukarıdaki kodda, ent.Open
veritabanıyla bağlantı kurmak ve bir istemci örneği döndürmekten sorumludur; client.Schema.Create
ise gerçek otomatik göç işlemini yürütür.
3. Otomatik Göçün İleri Düzey Uygulamaları
3.1 Sütun ve İndeksleri Silme
Bazı durumlarda, artık gerekmeyen sütunları veya indeksleri veritabanı şemasından kaldırmamız gerekebilir. Bu durumda WithDropColumn
ve WithDropIndex
seçeneklerini kullanabiliriz. Örneğin:
// Sütun ve indeksleri silme seçenekleriyle göçü çalıştır
err = client.Schema.Create(
ctx,
migrate.WithDropIndex(true),
migrate.WithDropColumn(true),
)
Bu kod parçacığı, otomatik göç sırasında sütunları ve indeksleri silme konfigürasyonunu etkinleştirir. ent
, göçü gerçekleştirirken şema tanımında bulunmayan herhangi bir sütun veya indeksi silecektir.
3.2 Küresel Benzersiz Kimlik
SQL veritabanlarında, varsayılan olarak, birincil anahtarlar her tablo için 1'den başlar ve farklı varlık türleri aynı kimliği paylaşabilir. Bazı uygulama senaryolarında, GraphQL kullanılırken farklı varlık türlerinin kimlikleri için küresel benzersizlik sağlamak gerekebilir. ent
'te bunu WithGlobalUniqueID
seçeneği kullanarak yapılandırabiliriz:
// Her varlık için evrensel benzersiz kimliklerle göçü çalıştır
if err := client.Schema.Create(ctx, migrate.WithGlobalUniqueID(true)); err != nil {
log.Fatalf("Veritabanı şeması oluşturulamadı: %v", err)
}
WithGlobalUniqueID
seçeneği etkinleştirildikten sonra, ent
her varlığa 2^32 aralıkta bir kimlik atayarak küresel benzersizliği sağlayacaktır.
3.3 Çevrimdışı Mod
Çevrimdışı mod, şema değişikliklerinin veritabanında doğrudan uygulanması yerine bir io.Writer
'a yazılmasına olanak tanır. Bu, değişikliklerin etkili olmadan önce SQL komutlarını doğrulamak veya manuel olarak yürütmek için bir SQL betiği oluşturmak için faydalıdır. Örneğin:
// Göç (migration) değişikliklerini bir dosyaya aktar
f, err := os.Create("migrate.sql")
if err != nil {
log.Fatalf("Göç dosyası oluşturulamadı: %v", err)
}
defer f.Close()
if err := client.Schema.WriteTo(ctx, f); err != nil {
log.Fatalf("Veritabanı şema değişiklikleri yazdırılamadı: %v", err)
}
Bu kod, göç (migration) değişikliklerini "migrate.sql" adlı bir dosyaya yazacaktır. Pratikte, geliştiriciler doğrudan standart çıktıya yazdırabilir veya inceleme veya kayıt tutma amaçlı bir dosyaya yazabilir.
4. Yabancı Anahtar Desteği ve Özel Kancalar
4.1 Yabancı Anahtarları Etkinleştirme veya Devre Dışı Bırakma
Ent'te yabancı anahtarlar, varlıklar arasındaki ilişkileri (kenarlar) tanımlayarak uygulanır ve bu yabancı anahtar ilişkileri, veri bütünlüğünü ve tutarlılığını sağlamak üzere otomatik olarak veritabanı düzeyinde oluşturulur. Bununla birlikte, belirli durumlarda, performans optimizasyonu veya veritabanının yabancı anahtarı desteklememesi gibi durumlarda bunları devre dışı bırakmayı seçebilirsiniz.
Göçlerde yabancı anahtar kısıtlamalarını etkinleştirme veya devre dışı bırakma işlemini, WithForeignKeys
yapılandırma seçeneği aracılığıyla kontrol edebilirsiniz:
// Yabancı anahtarları etkinleştir
err = client.Schema.Create(
ctx,
migrate.WithForeignKeys(true),
)
if err != nil {
log.Fatalf("Yabancı anahtarlarla şema kaynakları oluşturulurken hata oluştu: %v", err)
}
// Yabancı anahtarları devre dışı bırak
err = client.Schema.Create(
ctx,
migrate.WithForeignKeys(false),
)
if err != nil {
log.Fatalf("Yabancı anahtarlar olmadan şema kaynakları oluşturulurken hata oluştu: %v", err)
}
Bu yapılandırma seçeneği, Schema.Create
çağrılırken geçirilmelidir ve belirtilen değere göre oluşturulan DDL'de yabancı anahtar kısıtlamalarını içerip içermeme durumunu belirler.
4.2 Göç Kancalarının Uygulanması
Göç kancaları, göç yürütme işleminin farklı aşamalarında eklenip yürütülebilen özel mantıksal işlemlerdir. Veritabanı göçünden önce/sonra belirli mantık işlemlerini gerçekleştirmek için oldukça faydalıdır, örneğin göç sonuçlarını doğrulama ve veri ön yükleme gibi.
İşte özel göç kancalarının nasıl uygulanacağına dair bir örnek:
func customHook(next schema.Creator) schema.Creator {
return schema.CreateFunc(func(ctx context.Context, tables ...*schema.Table) error {
// Göçten önce yürütülecek özel kod
// Örneğin, günlükleme, belirli ön koşulların kontrolü vb.
log.Println("Göçten önce özel mantık")
// Sonraki kancayı veya varsayılan göç mantığını çağır
err := next.Create(ctx, tables...)
if err != nil {
return err
}
// Göçten sonra yürütülecek özel kod
// Örneğin, temizlik, veri göçü, güvenlik kontrolleri vb.
log.Println("Göçten sonra özel mantık")
return nil
})
}
// Göçte özel kancaların kullanılması
err := client.Schema.Create(
ctx,
schema.WithHooks(customHook),
)
if err != nil {
log.Fatalf("Özel göç kancalarının uygulanmasında hata oluştu: %v", err)
}
Kancalar, karmaşık göçler için güçlü ve vazgeçilmez araçlardır ve ihtiyaç duyulduğunda doğrudan veritabanı göç davranışını kontrol etme yeteneği sağlar.
5. Sürümlenmiş Göçler
5.1 Sürümlenmiş Göçlere Giriş
Sürümlenmiş göç, veritabanı göçlerini yönetmek için bir desen olup geliştiricilere veritabanı yapısındaki değişiklikleri belirli bir dizi veritabanı değişiklik komutlarını içeren birden çok sürüme bölmelerine olanak tanır. Otomatik Göç'e kıyasla, sürümlenmiş göç daha ince kontrol sağlayarak veritabanı yapısı değişikliklerinin izlenebilirliğini ve geri alınabilirliğini garanti altına alır.
Sürümlenmiş göçün temel avantajı, ileri ve geri göç (yükseltme veya geri alma) desteğidir, bu da geliştiricilere ihtiyaca göre belirli değişiklikleri uygulamalarına, geri almalarına veya atlamalarına olanak tanır. Bir ekip içinde işbirliği yapıldığında, sürümlenmiş göç, her üyenin aynı veritabanı yapısı üzerinde çalışmasını sağlayarak tutarsızlık kaynaklı sorunları azaltır.
Otomatik göç genellikle geri alınamaz, varlık modellerinin en son durumuna eşleşen SQL ifadeleri oluşturur ve yürütür, genellikle geliştirme aşamalarında veya küçük projelerde kullanılır.
5.2 Sürümlenmiş Göçlerin Kullanımı
1. Atlas Aracının Kurulumu
Versiyonlanmış göçlerden önce, sisteminize Atlas
aracını kurmanız gerekmektedir. Atlas
, birden fazla veritabanı sistemini destekleyen, veritabanı şema değişikliklerini yönetmek için güçlü özellikler sunan bir göç aracıdır.
macOS + Linux
curl -sSf https://atlasgo.sh | sh
Homebrew
brew install ariga/tap/atlas
Docker
docker pull arigaio/atlas
docker run --rm arigaio/atlas --help
Windows
https://release.ariga.io/atlas/atlas-windows-amd64-latest.exe
2. Mevcut Varlık Tanımlarına Göre Göç Dosyalarının Oluşturulması
atlas migrate diff migration_name \
--dir "file://ent/migrate/migrations" \
--to "ent://ent/schema" \
--dev-url "docker://mysql/8/ent"
3. Uygulama Göç Dosyaları
Göç dosyaları oluşturulduktan sonra, bunlar geliştirme, test veya üretim ortamlarına uygulanabilir. Genellikle, bu göç dosyalarını önce bir geliştirme veya test veritabanına uygular ve beklediğiniz gibi çalıştıklarından emin olursunuz. Ardından, aynı göç adımları üretim ortamında gerçekleştirilir.
atlas migrate apply \
--dir "file://ent/migrate/migrations" \
--url "mysql://root:pass@localhost:3306/example"
Göç dosyalarını uygulamak için atlas migrate apply
komutunu kullanarak, göç dosyası dizinini belirleyin (--dir
) ve hedef veritabanının URL'sini (--url
) belirtin.