Ön Hazırlık ve Gereksinimler
Veritabanı geçişlerine başlamadan önce geliştirme ortamınızın hazır olduğundan emin olmalısınız. Bu eğitimde Node.js 20+ sürümü ve ilişkisel bir veritabanı olan PostgreSQL kullanılacaktır.
- Node.js ve npm (veya pnpm/yarn) yüklü olmalıdır.
- Projenizin kök dizininde bir
package.jsondosyası bulunmalıdır. - Veritabanı bağlantı bilgilerini saklamak için
dotenvpaketi kullanılmalıdır.
Gerekli paketleri projenize dahil etmek için terminalinizde şu komutu çalıştırın:
npm install sequelize sequelize-cli pg pg-hstore dotenv
Bu paketler, veritabanı ile Node.js arasında bir köprü kurarak, şema değişikliklerini kod üzerinden yönetmemize olanak tanır.
Adım Adım Migration Yapılandırması
Sequelize CLI, veritabanı geçişlerini yönetmek için standart bir klasör yapısı sunar. İlk olarak konfigürasyon dosyasını oluşturarak işe başlayalım. Bu işlem, veritabanı bağlantı ayarlarını tanımlayacağımız config/config.json dosyasını oluşturur.
npx sequelize-cli init
Bu komut, projenizde config, models, migrations ve seeders klasörlerini oluşturacaktır. config/config.json dosyasını açarak veritabanı kimlik bilgilerinizi (kullanıcı adı, şifre, veritabanı adı) güncelleyin.
Kritik Uyarı: Veritabanı şifrelerinizi asla doğrudanconfig.jsondosyasına yazmayın. Bunun yerine ortam değişkenleri (environment variables) kullanarakprocess.env.DB_PASSWORDgibi bir yapı tercih edin.
İlk Migration Dosyasını Oluşturma
Bir tablo oluşturmak veya mevcut bir tabloyu değiştirmek için migration dosyası üretmeniz gerekir. Örneğin, "Kullanıcılar" tablosu oluşturmak için aşağıdaki komutu kullanın.
npx sequelize-cli migration:generate --name create-users-table
Bu komut, migrations/ klasörü içerisinde zaman damgası içeren bir dosya oluşturur. Bu dosya, veritabanına uygulanacak değişiklikleri tanımlayacağımız yerdir.
Migration Dosyasını Kodlama
Oluşturulan dosyanın içinde up ve down fonksiyonlarını göreceksiniz. up fonksiyonu geçişi ileri taşırken, down fonksiyonu bir hata durumunda yapılan değişikliği geri alır.
'use strict';
module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.createTable('Users', {
id: { type: Sequelize.INTEGER, primaryKey: true, autoIncrement: true },
username: { type: Sequelize.STRING, allowNull: false },
email: { type: Sequelize.STRING, unique: true },
createdAt: { type: Sequelize.DATE, allowNull: false },
updatedAt: { type: Sequelize.DATE, allowNull: false }
});
},
down: async (queryInterface, Sequelize) => {
await queryInterface.dropTable('Users');
}
};
Bu kod bloğu, veritabanında Users tablosunu oluşturur. allowNull: false kısıtlaması, veri bütünlüğünü korumak için zorunludur.
Migration İşlemini Çalıştırma ve Test Etme
Hazırladığınız migration dosyasını veritabanına uygulamak için şu komutu kullanın. Bu komut, henüz çalıştırılmamış tüm migration dosyalarını veritabanına yansıtır.
npx sequelize-cli db:migrate
İşlemin başarılı olup olmadığını kontrol etmek için veritabanı yönetim aracınızdan (örneğin pgAdmin veya terminal üzerinden psql) SequelizeMeta tablosuna bakabilirsiniz. Bu tablo, hangi migration'ların başarıyla tamamlandığını tutar.
Veritabanı Geçiş Yöntemlerinin Karşılaştırılması
Node.js dünyasında migration yönetimi için kullanılan farklı yaklaşımlar mevcuttur. İhtiyacınıza göre en uygun olanı seçmelisiniz.
| Yöntem | Avantajı | Dezavantajı |
|---|---|---|
| Sequelize CLI | Geniş topluluk, güçlü ORM desteği | Öğrenme eğrisi biraz yüksek |
| Knex.js | Daha hafif, SQL'e yakın kontrol | ORM özellikleri daha kısıtlı |
| Prisma | Tip güvenliği (Type-safe), hızlı geliştirme | Büyük projelerde karmaşık olabilir |
Sıkça Sorulan Sorular
Migration dosyasında hata yaparsam ne yapmalıyım?
Eğer migration henüz production ortamına çıkmadıysa, npx sequelize-cli db:migrate:undo komutu ile son işlemi geri alabilir, dosyayı düzenleyip tekrar db:migrate yapabilirsiniz.
Production ortamında migration nasıl yapılır?
Production ortamında migration'ları mutlaka bir CI/CD pipeline'ı üzerinden, veritabanı yedeği aldıktan sonra çalıştırmalısınız.
Migration dosyalarını neden versiyon kontrol sistemine (Git) eklemeliyim?
Ekip arkadaşlarınızın aynı veritabanı şemasına sahip olması için migration dosyaları şarttır. Git üzerinden bu dosyaları paylaşmak, "benim bilgisayarımda çalışıyor" sorununu ortadan kaldırır.
Mevcut bir tabloya yeni sütun nasıl eklenir?
Yeni bir migration dosyası oluşturup queryInterface.addColumn metodunu kullanarak sütun ekleme işlemini gerçekleştirebilirsiniz.
Veritabanı şifrelerini nasıl korumalıyım?
Her zaman .env dosyası kullanın ve bu dosyayı .gitignore içerisine ekleyerek asla uzak sunucuya göndermeyin.
Güvenlik Sorumluluk Reddi: Bu rehberdeki kod örnekleri eğitim amaçlıdır. Production ortamında veritabanı işlemleri yapmadan önce mutlaka veritabanı yedeği alınız ve SQL injection riskine karşı her zaman parametreli sorgular (ORM'lerin sunduğu yöntemler) kullanınız.
İleri Seviye Migration Stratejileri: Veri Taşıma ve Dönüştürme
Bazen sadece tablo yapısını değiştirmek yeterli olmaz; mevcut verilerin yeni şemaya uyumlu hale getirilmesi gerekir. Örneğin, users tablosundaki name sütununu first_name ve last_name olarak ayırmanız gerekebilir. Bu tür durumlarda migration dosyası içerisinde veri manipülasyonu yapmanız şarttır.
Aşağıdaki örnek, mevcut veriyi parçalayarak yeni sütunlara aktaran bir migration stratejisini göstermektedir:
module.exports = {
up: async (queryInterface, Sequelize) => {
// 1. Yeni sütunları ekle
await queryInterface.addColumn('Users', 'first_name', Sequelize.STRING);
await queryInterface.addColumn('Users', 'last_name', Sequelize.STRING);
// 2. Mevcut veriyi işle
const users = await queryInterface.sequelize.query('SELECT id, name FROM Users');
for (const user of users[0]) {
const parts = user.name.split(' ');
await queryInterface.sequelize.query(
'UPDATE Users SET first_name = :first, last_name = :last WHERE id = :id',
{ replacements: { first: parts[0], last: parts[1] || '', id: user.id } }
);
}
// 3. Eski sütunu kaldır
await queryInterface.removeColumn('Users', 'name');
},
down: async (queryInterface, Sequelize) => {
// Geri alma işlemi (Rollback)
await queryInterface.addColumn('Users', 'name', Sequelize.STRING);
// ... veri birleştirme mantığı buraya yazılmalı
}
};
Migration Süreçlerinde Performans ve Kilitleme Sorunları
Büyük ölçekli veritabanlarında (milyonlarca satır içeren tablolar), ALTER TABLE işlemleri veritabanını kilitleyebilir ve uygulamanızın yanıt vermemesine neden olabilir. Bu durumu yönetmek için şu stratejileri izlemelisiniz:
- Batch İşlemler: Veri taşıma işlemlerini tek seferde yapmak yerine küçük parçalar (chunk) halinde gerçekleştirin.
- Online DDL: Mümkünse veritabanınızın desteklediği "online schema change" araçlarını (örneğin MySQL için
gh-ostveyapt-online-schema-change) kullanın. - Index Yönetimi: Çok büyük tablolarda yeni bir index eklemek, tablonun kilitlenmesine yol açabilir. Bunun yerine
CONCURRENTLY(PostgreSQL için) anahtar kelimesini kullanmayı değerlendirin.
Özellikle down fonksiyonlarını yazarken, veritabanı yedeğinin önemini asla unutmayın. Karmaşık bir migration işlemi sırasında hata alırsanız, veritabanı tutarsız bir durumda kalabilir. Bu yüzden her zaman transaction bloklarını kullanın:
up: async (queryInterface, Sequelize) => {
const transaction = await queryInterface.sequelize.transaction();
try {
await queryInterface.addColumn('Orders', 'status', Sequelize.INTEGER, { transaction });
await transaction.commit();
} catch (err) {
await transaction.rollback();
throw err;
}
}
Migration Hata Ayıklama (Debugging) İpuçları
Migration hataları genellikle veritabanı kısıtlamaları (constraints) veya veri tipi uyuşmazlıklarından kaynaklanır. Hata ayıklama sürecini hızlandırmak için şu adımları izleyin:
- SQL Loglarını Aktif Edin: Sequelize konfigürasyonunuzda
logging: console.logparametresini açarak hangi SQL sorgusunun hata verdiğini anlık görün. - Dry Run: Değişiklikleri uygulamadan önce SQL çıktısını bir dosyaya yazdırarak inceleyin.
- State Kontrolü:
SequelizeMetatablosunu kontrol ederek, hangi migration dosyasının en son başarıyla çalıştırıldığını doğrulayın.
Sonuç
Node.js ile veritabanı geçişleri, projenizin sürdürülebilirliği için vazgeçilmez bir yetenektir. Sequelize CLI veya alternatif araçlarla şema değişikliklerini yönetmek, hataları minimize eder ve geliştirme sürecini hızlandırır. Bir sonraki adım olarak, veritabanı işlemlerinizi daha güvenli hale getirmek için Veritabanı Seed (Tohumlama) işlemlerini öğrenerek test verilerinizi nasıl otomatik oluşturacağınızı araştırmanızı öneririm.


Yorumlar (0)
Yorum Yaz