Database Migrations: Schema-Versionierung | Enjyn Gruppe
Hallo Welt
Hallo Welt
Original Lingva Deutsch
Übersetzung wird vorbereitet...
Dieser Vorgang kann bis zu 60 Sekunden dauern.
Diese Seite wird erstmalig übersetzt und dann für alle Besucher gespeichert.
0%
DE Zurück zu Deutsch
Übersetzung durch Lingva Translate

235 Dokumentationen verfügbar

Wissensdatenbank

Database Migrations Versionierung

Zuletzt aktualisiert: 20.01.2026 um 10:02 Uhr

Database Migrations: Schema-Versionierung

Migrations machen Datenbankänderungen reproduzierbar und versionierbar. Lernen Sie, wie Sie Schema-Änderungen sicher deployen.

Warum Migrations?

❌ Ohne Migrations:
  • "Das SQL-Script hat Max letzte Woche ausgeführt..."
  • "Auf Production fehlt die neue Spalte!"
  • "Welche Version hat die Staging-DB?"
✅ Mit Migrations:
  • Schema-Änderungen im Git versioniert
  • Automatisches Deployment möglich
  • Rollback bei Problemen
  • Gleicher Stand auf allen Umgebungen

Node.js: Knex Migrations

npm install knex pg
npx knex init
// knexfile.js
module.exports = {
  development: {
    client: 'postgresql',
    connection: process.env.DATABASE_URL,
    migrations: {
      directory: './migrations'
    }
  }
};
# Migration erstellen
npx knex migrate:make create_users_table
// migrations/20240115120000_create_users_table.js
exports.up = function(knex) {
  return knex.schema.createTable('users', table => {
    table.increments('id').primary();
    table.string('email').notNullable().unique();
    table.string('name').notNullable();
    table.string('password_hash').notNullable();
    table.boolean('is_active').defaultTo(true);
    table.timestamps(true, true);
  });
};

exports.down = function(knex) {
  return knex.schema.dropTable('users');
};
# Migrations ausführen
npx knex migrate:latest

# Rollback
npx knex migrate:rollback

# Status
npx knex migrate:status

PHP: Laravel Migrations

# Migration erstellen
php artisan make:migration create_users_table
<?php
// database/migrations/2024_01_15_120000_create_users_table.php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    public function up(): void
    {
        Schema::create('users', function (Blueprint $table) {
            $table->id();
            $table->string('email')->unique();
            $table->string('name');
            $table->string('password');
            $table->boolean('is_active')->default(true);
            $table->timestamps();
        });
    }

    public function down(): void
    {
        Schema::dropIfExists('users');
    }
};
# Migrations ausführen
php artisan migrate

# Rollback
php artisan migrate:rollback
php artisan migrate:rollback --step=2

# Status
php artisan migrate:status

# Reset und neu ausführen
php artisan migrate:fresh

Python: Alembic (SQLAlchemy)

pip install alembic
alembic init migrations
# alembic.ini
sqlalchemy.url = postgresql://user:pass@localhost/mydb
# Migration erstellen
alembic revision --autogenerate -m "create users table"
# migrations/versions/abc123_create_users_table.py
from alembic import op
import sqlalchemy as sa

revision = 'abc123'
down_revision = None

def upgrade():
    op.create_table(
        'users',
        sa.Column('id', sa.Integer(), primary_key=True),
        sa.Column('email', sa.String(255), nullable=False, unique=True),
        sa.Column('name', sa.String(255), nullable=False),
        sa.Column('password_hash', sa.String(255), nullable=False),
        sa.Column('is_active', sa.Boolean(), default=True),
        sa.Column('created_at', sa.DateTime(), server_default=sa.func.now()),
        sa.Column('updated_at', sa.DateTime(), onupdate=sa.func.now())
    )

def downgrade():
    op.drop_table('users')
# Migrations ausführen
alembic upgrade head

# Rollback
alembic downgrade -1

# Status
alembic current
alembic history

Raw SQL Migrations (Flyway)

# Dateistruktur
migrations/
├── V1__Create_users_table.sql
├── V2__Add_email_index.sql
└── V3__Create_posts_table.sql

# V1__Create_users_table.sql
CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    email VARCHAR(255) NOT NULL UNIQUE,
    name VARCHAR(255) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

# V2__Add_email_index.sql
CREATE INDEX idx_users_email ON users(email);

# Docker
docker run -v ./migrations:/flyway/sql flyway/flyway \
  -url=jdbc:postgresql://host:5432/db \
  -user=user -password=pass migrate

Best Practices

// ✅ Kleine, fokussierte Migrations
// Migration 1: Create table
// Migration 2: Add index
// Migration 3: Add column

// ❌ Alles in einer Migration
// Migration 1: Create table + indexes + seed data + ...

// ✅ Idempotente Migrations (wenn möglich)
exports.up = function(knex) {
  return knex.schema.hasTable('users').then(exists => {
    if (!exists) {
      return knex.schema.createTable('users', ...);
    }
  });
};

// ✅ Down-Migration immer implementieren
exports.down = function(knex) {
  return knex.schema.dropTableIfExists('users');
};

Spalten sicher ändern

// ❌ Gefährlich: Spalte umbenennen
ALTER TABLE users RENAME COLUMN name TO full_name;
// Alte App-Version schlägt fehl!

// ✅ Sicher: Expand-Contract Pattern
// 1. Neue Spalte hinzufügen
ALTER TABLE users ADD COLUMN full_name VARCHAR(255);

// 2. Daten kopieren
UPDATE users SET full_name = name;

// 3. App-Code anpassen (beide Spalten unterstützen)

// 4. Deploy neue App-Version

// 5. Alte Spalte entfernen (separate Migration)
ALTER TABLE users DROP COLUMN name;

Große Tabellen migrieren

// ❌ Problematisch bei großen Tabellen
ALTER TABLE orders ADD COLUMN status VARCHAR(50) DEFAULT 'pending';
// Lockt die ganze Tabelle!

// ✅ Besser: In Schritten
// 1. Spalte ohne Default hinzufügen
ALTER TABLE orders ADD COLUMN status VARCHAR(50);

// 2. In Batches updaten
UPDATE orders SET status = 'pending'
WHERE id BETWEEN 1 AND 10000;

UPDATE orders SET status = 'pending'
WHERE id BETWEEN 10001 AND 20000;
-- ...

// 3. Default setzen für neue Rows
ALTER TABLE orders ALTER COLUMN status SET DEFAULT 'pending';

CI/CD Integration

# GitHub Actions
jobs:
  migrate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Run migrations
        run: |
          npm run migrate
        env:
          DATABASE_URL: ${{ secrets.DATABASE_URL }}

      - name: Deploy
        run: ./deploy.sh
💡 Tipp: Testen Sie Migrations immer zuerst auf einer Kopie der Production-Datenbank. Nutzen Sie das Enjyn Status Monitoring um Deployments zu überwachen.

Weitere Informationen

Enjix Beta

Enjyn AI Agent

Hallo 👋 Ich bin Enjix — wie kann ich dir helfen?
120