1. Einführung in Atlas

atlas

Atlas ist ein sprachunabhängiges Tool, das speziell für das Management und die Migration von Datenbankschemata unter Verwendung moderner DevOps-Prinzipien entwickelt wurde. Es bietet zwei Workflow-Optionen:

  • Deklarativ: Ähnlich wie Terraform vergleicht Atlas den aktuellen Zustand der Datenbank mit dem gewünschten Zustand, der unter Verwendung von HCL, SQL oder ORM-Schema definiert ist. Basierend auf diesem Vergleich generiert und führt es einen Migrationsplan aus, um die Datenbank in ihren gewünschten Zustand zu überführen.
  • Versioniert: Im Gegensatz zu anderen Tools plant Atlas automatisch die Schema-Migrationen für Sie. Benutzer können ihr gewünschtes Datenbankschema mit HCL, SQL oder ihrem gewählten ORM beschreiben und mit Atlas die erforderlichen Migrationen planen, überprüfen und anwenden.

Ein wesentlicher Vorteil von Atlas ist die Vereinfachung der Komplexität des Datenbankmanagements, sodass eine einfache Versionskontrolle, Zusammenarbeit und Implementierung möglich sind.

2. Atlas installieren

Bevor Sie Atlas zur Verwaltung von Datenbankversionen verwenden können, müssen Sie es installieren. Nachfolgend finden Sie die Installationsanweisungen für verschiedene Plattformen.

2.1 Installation auf macOS und Linux

Auf macOS- oder Linux-Systemen können Sie die neueste Version von Atlas mithilfe des folgenden Befehls herunterladen und installieren:

curl -sSf https://atlasgo.sh | sh

Dieser Befehl erkennt automatisch die Betriebssystemversion, lädt die geeignete Build-Version herunter und platziert die Atlas-Binärdatei im ausführbaren Pfad.

2.2 Installation über Homebrew

Wenn Sie macOS verwenden und bereits den Homebrew Paketmanager installiert haben, ist die Installation von Atlas so einfach wie das Ausführen des Befehls:

brew install ariga/tap/atlas

Dadurch wird die neueste Version von Atlas aus dem Repository von Homebrew abgerufen und installiert.

2.3 Docker-Installation

Die Installation und Ausführung von Atlas über Docker ist eine schnelle und bequeme Methode, insbesondere für temporäres Testen oder für Benutzer, die keine zusätzliche Software auf ihrem Hostsystem installieren möchten.

Zuerst müssen Sie das Atlas Docker-Image herunterladen:

docker pull arigaio/atlas

Anschließend können Sie einen Hilfebefehl ausführen, um eine erfolgreiche Installation zu bestätigen:

docker run --rm arigaio/atlas --help

Wenn der Container auf das Hostnetzwerk oder lokale Verzeichnisse zugreifen muss, verwenden Sie das --net=host-Flag und mounten Sie die erforderlichen Verzeichnisse:

docker run --rm --net=host \
  -v $(pwd)/migrations:/migrations \
  arigaio/atlas migrate apply \
  --url "mysql://root:pass@:3306/test"

2.4 Installation unter Windows

Laden Sie die Binärdatei herunter, https://release.ariga.io/atlas/atlas-windows-amd64-latest.exe, und fügen Sie den Installationspfad der Systemumgebungsvariable PATH hinzu.

3. Exportieren der vorhandenen Datenbanktabellenstruktur mit Atlas

Atlas bietet das Befehlskennwort atlas schema inspect, das verwendet werden kann, um die Struktur einer vorhandenen Datenbank zu exportieren. Dieser Befehl unterstützt das Lesen von Datenbankbeschreibungen von der Datenbank-URL und gibt sie in drei verschiedenen Formaten aus: dem Standard-Atlas-HCL-Format, dem SQL-Format und dem JSON-Format. In dieser Anleitung zeigen wir, wie die Atlas-HCL- und SQL-Formate verwendet werden, da das JSON-Format typischerweise für die Verarbeitung von Ausgaben mit jq verwendet wird.

Um eine lokal laufende MySQL-Instanz zu inspizieren und die Ausgabe in eine Datei mit dem Namen schema.hcl zu schreiben, verwenden Sie den folgenden Befehl:

atlas schema inspect -u "mysql://root:pass@localhost:3306/example" > schema.hcl

Öffnen Sie die Datei schema.hcl, um die Atlas-Tabellenstrukturdefinition anzuzeigen, die die Datenbank beschreibt (HCL ist ein datenbankunabhängiges Tabellenstrukturkonfigurationsformat, das von Atlas definiert ist). Diese Datei wird beispielsweise den folgenden Inhalt enthalten:

table "users" {
  schema = schema.example
  column "id" {
    null = false
    type = int
  }
  column "name" {
    null = true
    type = varchar(100)
  }
  primary_key {
    columns = [column.id]
  }
}

Dieser Codeblock stellt eine Tabellenstruktur mit den Spalten id und name dar. Das Feld schema verweist auf die anderswo in diesem Dokument definierte Modelldefinition example. Darüber hinaus gibt der Unterblock primary_key die Spalte id als Primärschlüssel für die Tabelle an. Atlas strebt danach, die Syntax der verwendeten Datenbank zu imitieren. In diesem Beispiel hat die Spalte id den Typ int, während die Spalte name den Typ varchar(100) hat.

Ähnlich können Sie zur Exportierung einer SQL-Modelldefinition der Datenbank den folgenden Befehl verwenden:

atlas schema inspect -u "mysql://root:pass@localhost:3306/example" --format '{{ sql . }}' > schema.sql

Öffnen Sie die Datei schema.sql, um die SQL-Beschreibung der Datenbank anzuzeigen, die typischerweise einige CREATE TABLE-Anweisungen enthält.

Diese Methode erleichtert das Verständnis der Details der bestehenden Datenbanktabellenstruktur und liefert eine genaue Referenz für nachfolgende versionierte Migrationen.

4.1 Deklarativer Workflow

Der deklarative Workflow von Atlas ermöglicht es Benutzern, den gewünschten endgültigen Zustand der Datenbank deklarativ zu definieren. Benutzer müssen nur beschreiben, wie der endgültige Zustand des Datenbankschemas sein soll, und das Atlas-Tool generiert und führt automatisch Migrationspläne aus, um das Datenbankschema sicher vom aktuellen Zustand zu diesem erwarteten Zustand zu überführen.

So verwenden Sie den deklarativen Workflow, um den gewünschten Datenbankzustand zu definieren und zu erreichen:

4.1.1 Definition der Zieltabellenstruktur

Zunächst müssen Sie eine Datei erstellen, die die erwartete Datenbankstruktur definiert, die im HCL-, SQL- oder ORM (Object-Relational Mapping)-Format vorliegen kann.

Nehmen wir zum Beispiel das HCL-Format und definieren eine neue Tabelle blog_posts:

table "blog_posts" {
  schema = schema.example
  column "id" {
    null = false
    type = int
  }
  column "title" {
    null = true
    type = varchar(100)
  }
  column "body" {
    null = true
    type = text
  }
  column "author_id" {
    null = true
    type = int
  }
  primary_key {
    columns = [column.id]
  }
  foreign_key "author_fk" {
    columns     = [column.author_id]
    ref_columns = [table.users.column.id]
  }
}

Tipp: Das Syntaxformat von HCL wird in einem späteren Abschnitt behandelt.

4.1.2 Migration mit dem Atlas-Tool durchführen

Nachdem die Definition der Datenbanktabellenstruktur abgeschlossen ist, können Sie das Befehlskennwort schema apply von Atlas verwenden, um die Migration durchzuführen.

atlas schema apply \
  -u "mysql://root:pass@localhost:3306/example" \
  --to file://schema.hcl

Nach Ausführung des obigen Befehls vergleicht Atlas das vorhandene Datenbankschema mit dem in der Datei definierten Schema, generiert einen Migrationsplan und fragt den Benutzer nach Bestätigung zur Ausführung. Sobald der Benutzer den Ausführungsplan bestätigt, führt Atlas die Migration auf der Datenbank durch und aktualisiert sie auf den gewünschten Zustand.

4.2 Versionierter Workflow

Der versionierte Workflow ist ein weiterer von Atlas unterstützter Anwendungsmodus, der manchmal als "Änderungsbasierte Migration" bezeichnet wird. Er eignet sich für Szenarien, in denen Datenbankschemaänderungen versioniert und im Code-Review-Prozess überprüft werden müssen.

Die Schritte des versionierten Workflows umfassen:

4.2.1 Unterschiede berechnen

Vor dem Start der Migration ist es notwendig, die aktuelle Datenbankstruktur mit dem gewünschten Zustand zu vergleichen und die Unterschiede zwischen den beiden festzustellen. Dies kann durch Ausführen des Befehls atlas migrate diff erreicht werden.

atlas migrate diff create_blog_posts \
  --dir "file://migrations" \
  --to "file://schema.hcl" \
  --dev-url "docker://mysql/8/example"

Das --dir gibt die URL des Migrationsordners an und ist standardmäßig auf file://migrations eingestellt. Das --to gibt die URL des gewünschten Zustands an (z.B. Ihre Entwicklungsdatenbankumgebung), und --dev-url bietet eine URL für eine Entwicklungsdatenbank zur Berechnung der Unterschiede (beachten Sie, dass diese --dev-url eine leere Datenbank angeben muss, die Atlas zur Berechnung der Unterschiede verwendet).

Tipp: Wenn Sie SQL-Dateien generieren möchten, finden Sie im vorherigen Abschnitt Informationen zur Einstellung des Formats mithilfe des --format-Parameters.

4.2.2 Migrationsänderungen anwenden

Nach Abschluss der Unterschiedsberechnung generiert Atlas zwei Migrationsdateien, die im Ordner migrations gespeichert sind. Wenn z.B. das ausgewählte Format SQL ist, enthalten die durch den diff-Befehl generierten Dateien, wie die folgende SQL-Datei, Migrationsbefehle zur Erstellung einer neuen Tabelle:

-- Tabelle "blog_posts" erstellen
CREATE TABLE `blog_posts` (
  `id` int NOT NULL,
  `title` varchar(100) DEFAULT NULL,
  `body` text DEFAULT NULL,
  `author_id` int NULL REFERENCES `users`(id),
  PRIMARY KEY (`id`)
);

Sobald die Migrationsdateien generiert sind, können Sie Versionskontrollwerkzeuge (z.B. Git) verwenden, um diese Änderungen zu verwalten. Dieser Ansatz ermöglicht es, zahlreiche Änderungen an der Datenbanktabellenstruktur in der Entwicklungsumgebung vorzunehmen und bei Veröffentlichung die Entwicklungsumgebung mit der UAT-Umgebung mithilfe von Atlas-Befehlen zu vergleichen, um Migrationsdateien für die Datenbanktabellenstruktur zu generieren. Diese Migrationsdateien können dann auf die UAT- und Produktionsumgebungen angewendet werden, um die Datenbank zu aktualisieren.

Diese beiden Workflows, Deklarativ und Versioniert, bieten Flexibilität für verschiedene Entwicklungs- und Bereitstellungsmodi und ermöglichen es Teams, die Methode zu wählen, die am besten zu den Projektanforderungen für das Management von Datenbankschemänderungen passt.

5. Beschreibung des HCL-Formats

5.1 Einführung

HCL ist eine deklarative Sprache, die zur Beschreibung von Datenbanktabellenstrukturdefinitionen verwendet wird. Atlas verwendet das HCL-Format, um Datenbankschemata zu schreiben, und bietet eine umfangreiche Struktur zur Beschreibung verschiedener Aspekte der Datenbank. Der Vorteil von HCL liegt in seiner Lesbarkeit, der einfachen Wartung und der Unterstützung von Funktionen wie Variableneinspritzung und zusätzlichen Annotationen.

Tipp: Wenn Ihr Projekt sich an mehrere Datenbanken anpassen muss, kann die Beschreibung von Tabellenstrukturen in einer datenbankagnostischen Weise mithilfe von HCL sehr bequem sein.

5.2 schema-Objekt

Das schema-Objekt wird verwendet, um ein Datenbankschema zu beschreiben. In MySQL und SQLite repräsentiert es die DATENBANK, während es in PostgreSQL das SCHEMA repräsentiert. Eine HCL-Datei kann ein oder mehrere schema-Objekte enthalten.

schema "public" {
  comment = "Ein Schemakommentar"
}

schema "private" {}

5.3 table-Objekt

Das table-Objekt wird verwendet, um eine Tabelle in einer SQL-Datenbank zu beschreiben, einschließlich Spalten, Indizes, Einschränkungen und verschiedenen zusätzlichen Eigenschaften, die von verschiedenen Datenbanktreibern unterstützt werden.

table "users" {
  schema = schema.public
  column "id" {
    type = int
  }
  column "name" {
    type = varchar(255)
  }
  column "manager_id" {
    type = int
  }
  primary_key {
    columns = [
      column.id
    ]
  }
  index "idx_name" {
    columns = [
      column.name
    ]
    unique = true
  }
  foreign_key "manager_fk" {
    columns     = [column.manager_id]
    ref_columns = [table.users.column.id]
    on_delete   = CASCADE
    on_update   = NO_ACTION
  }
}

5.4 column-Objekt

Die column ist eine Unterressource von table, die verwendet wird, um die Spalten in der Tabelle zu definieren.

column "name" {
  type = text
  null = false
}

column "age" {
  type = integer
  default = 42
}

column "active" {
  type = tinyint(1)
  default = true
}

5.5 Objekt primary_key

Das Objekt primary_key ist eine Unterressource von table, die den Primärschlüssel der Tabelle definiert.

primary_key {
  columns = [spalte.id]
}

5.6 Objekt foreign_key

Das Objekt foreign_key ist eine Unterressource von table, die Spalten definiert, die auf Spalten in anderen Tabellen verweisen.

table "orders" {
  schema = schema.market
  // ...
  column "owner_id" {
    type = integer
  }
  foreign_key "owner_id" {
    columns     = [spalte.owner_id]
    ref_columns = [table.users.column.id]
    on_update   = NO_ACTION
    on_delete   = NO_ACTION
  }
}

5.7 Objekt index

Das Objekt index repräsentiert einen Index auf der Tabelle.

index "idx_name" {
  columns = [
    spalte.name
  ]
  unique = true
}