Schemaaktualisierungen vornehmen

Mit Spanner lassen sich Schemas ohne Ausfallzeit aktualisieren. Sie haben mehrere Möglichkeiten, das Schema einer vorhandenen Datenbank zu aktualisieren:

Unterstützte Schemaaktualisierungen

Für das Schema einer vorhandenen Datenbank unterstützt Spanner folgende Arten von Aktualisierungen:

  • Benanntes Schema hinzufügen oder löschen.
  • Erstellen einer neuen Tabelle Spalten in neuen Tabellen können NOT NULL sein.
  • Eine Tabelle löschen, sofern keine anderen Tabellen damit verschränkt sind und die zu löschende Tabelle keine sekundären Indexe hat.
  • Tabelle mit einem Fremdschlüssel erstellen oder löschen.
  • Hinzufügen oder entfernen eines Fremdschlüssels aus einer vorhandenen Tabelle.
  • Eine Nicht-Schlüsselspalte in eine Tabelle aufnehmen. Neue Nicht-Schlüsselspalten dürfen nicht NOT NULL sein.
    • Eine Nicht-Schlüsselspalte aus einer Tabelle löschen, sofern sie nicht von einem sekundären Index, einem Fremdschlüssel, einer gespeicherten generierten Spalte oder einer Prüfeinschränkung verwendet wird.
  • NOT NULL in eine Nicht-Schlüsselspalte aufnehmen und dabei ARRAY-Spalten ausschließen.
  • NOT NULL aus einer Nicht-Schlüsselspalte entfernen.
  • Eine STRING-Spalte in eine BYTES-Spalte ändern oder umgekehrt ( STRING in BYTES oder BYTES in STRING).
  • Eine PROTO-Spalte in eine BYTES-Spalte ändern oder umgekehrt ( PROTO in BYTES oder BYTES in PROTO).
  • Den Proto-Nachrichtentyp einer PROTO-Spalte ändern.
  • Mit ALTER PROTO BUNDLE neue Werte zu einer ENUM-Definition hinzufügen und vorhandene Werte umbenennen.
  • Nachrichten, die in einem PROTO BUNDLE definiert sind, auf beliebige Weise ändern, sofern die geänderten Felder dieser Nachrichten in keiner Tabelle als Schlüssel verwendet werden und die vorhandenen Daten den neuen Einschränkungen entsprechen.
  • Die Längenbeschränkung für einen STRING oder BYTES Typ (einschließlich auf MAX) erhöhen oder verringern, es sei denn, es ist eine Primärschlüssel spalte, die von einer oder mehreren untergeordneten Tabellen übernommen wird.
  • Die Längenbeschränkung für eine ARRAY<STRING>, ARRAY<BYTES> oder ARRAY<PROTO>-Spalte auf das zulässige Maximum erhöhen oder verringern.
  • Commit-Zeitstempel in Wert- und Primär schlüsselspalten aktivieren oder deaktivieren.
  • Sekundären Index hinzufügen oder entfernen.
  • Diagnoseeinschränkung zu einer vorhandenen Tabelle hinzufügen oder daraus entfernen.
  • Gespeicherte generierte Spalte zu einer vorhandenen Tabelle hinzufügen oder daraus entfernen.
  • Neues Statistikpaket für das Abfrageoptimierungstool erstellen.
  • Ansichten erstellen und verwalten.
  • Sequenzen erstellen und verwalten.
  • Datenbankrollen erstellen und Berechtigungen gewähren.
  • Den Standardwert einer Spalte festlegen, ändern oder löschen.
  • Die Datenbankoptionen ändern (z. B. default_leader oder version_retention_period).
  • Änderungsstreams erstellen und verwalten.
  • ML-Modelle erstellen und verwalten.

Nicht unterstützte Schemaaktualisierungen

Spanner unterstützt die folgenden Schemaaktualisierungen für eine vorhandene Datenbank nicht:

  • Wenn ein PROTO-Feld vom Typ ENUM vorhanden ist, auf das von einem Tabellen- oder Indexschlüssel verwiesen wird, können Sie keine ENUM-Werte aus den Proto-Enums entfernen. Das Entfernen von ENUM Werten aus Enums, die von ENUM<> Spalten verwendet werden, wird unterstützt, einschließlich wenn diese Spalten als Schlüssel verwendet werden.

  • Eine STRING(36)-Spalte in eine UUID-Spalte ändern oder umgekehrt ( STRING(36) in UUID oder UUID in STRING(36)).

Leistung während der Schemaaktualisierung

Schemaaktualisierungen in Spanner erfolgen ohne Ausfallzeiten. Wenn Sie einen Batch von DDL-Anweisungen an eine Spanner-Datenbank absetzen, können Sie ohne Unterbrechung weiter Daten in die Datenbank schreiben und aus ihr lesen, während Spanner die Aktualisierung als Vorgang mit langer Ausführungszeit ausführt.

Die Ausführungsdauer einer DDL-Anweisung hängt davon ab, ob die Aktualisierung eine Validierung von vorhandenen Daten oder einen Daten-Backfill voraussetzt. Wenn Sie beispielsweise die NOT NULL Annotation zu einer vorhandenen Spalte hinzufügen, muss Spanner alle Werte in der Spalte lesen, um sicherzustellen, dass die Spalte keine NULL Werte enthält. Wenn viele Daten validiert werden müssen, kann dieser Schritt lange dauern. Ein anderes Beispiel ist die Erweiterung einer Datenbank um einen Index: Spanner verwendet dann vorhandene Daten, um einen Backfill für den Index durchzuführen. In Abhängigkeit von der Definition des Index und der Größe der entsprechenden Basistabelle kann dieser Prozess viel Zeit in Anspruch nehmen. Wenn Sie jedoch einer Tabelle eine neue Spalte hinzufügen, sind keine vorhandenen Daten zu validieren, sodass Spanner die Aktualisierung schneller durchführen kann.

Zusammenfassend lässt sich sagen, dass Schemaaktualisierungen innerhalb von Minuten durchgeführt werden können, wenn Spanner keine vorhandenen Daten validieren muss. Schemaaktualisierungen mit Validierung können je nach Menge der zu validierenden vorhandenen Daten länger dauern. Allerdings erfolgt die Datenvalidierung im Hintergrund mit niedrigerer Priorität als Produktionstraffic. Schemaaktualisierungen, die eine Datenvalidierung voraussetzen, werden im nächsten Abschnitt ausführlicher erläutert.

Schemaaktualisierungen, die mit Ansichtsdefinitionen validiert werden

Wenn Sie ein Schema aktualisieren, prüft Spanner, ob die Abfragen, die zum Definieren vorhandener Ansichten verwendet werden, durch das Update nicht ungültig werden. Ist die Validierung erfolgreich, verläuft auch die Schemaaktualisierung erfolgreich. Wenn die Validierung nicht erfolgreich ist, schlägt die Schemaaktualisierung fehl. Weitere Informationen finden Sie unter Best Practices beim Erstellen von Ansichten.

Schemaaktualisierungen mit erforderlicher Datenvalidierung

Sie können Schemaaktualisierungen vornehmen, bei denen überprüft werden muss, ob die vorhandenen Daten den neuen Einschränkungen entsprechen. Wenn für eine Schemaaktualisierung eine Datenvalidierung erforderlich ist, lässt Spanner keine in Konflikt stehenden Schemaaktualisierungen der betroffenen Schemaentitäten zu und validiert die Daten im Hintergrund. Ist die Validierung erfolgreich, verläuft auch die Schemaaktualisierung erfolgreich. Wenn die Validierung nicht erfolgreich ist, schlägt die Schemaaktualisierung fehl. Validierungsvorgänge werden als lang laufende Vorgängeausgeführt. Anhand des Status dieser Vorgänge können Sie feststellen, ob sie erfolgreich beendet wurden oder fehlgeschlagen sind.

Angenommen, Sie haben die folgende music.proto-Datei mit einem RecordLabel-Enum und einer Songwriter-Protokollnachricht definiert:

  enum RecordLabel {
    COOL_MUSIC_INC = 0;
    PACIFIC_ENTERTAINMENT = 1;
    XYZ_RECORDS = 2;
  }

  message Songwriter {
    required string nationality   = 1;
    optional int64  year_of_birth = 2;
  }

So fügen Sie Ihrem Schema eine Songwriters-Tabelle hinzu:

GoogleSQL

CREATE PROTO BUNDLE (
  googlesql.example.music.Songwriter,
  googlesql.example.music.RecordLabel,
);

CREATE TABLE Songwriters (
  Id         INT64 NOT NULL,
  FirstName  STRING(1024),
  LastName   STRING(1024),
  Nickname   STRING(MAX),
  OpaqueData BYTES(MAX),
  SongWriter googlesql.example.music.Songwriter
) PRIMARY KEY (Id);

CREATE TABLE Albums (
  SongwriterId     INT64 NOT NULL,
  AlbumId          INT64 NOT NULL,
  AlbumTitle       STRING(MAX),
  Label            INT32
) PRIMARY KEY (SongwriterId, AlbumId);

In diesem Fall sind folgende Schemaaktualisierungen zulässig, die jedoch validiert werden müssen und je nach Menge der vorhandenen Daten länger dauern können:

  • Die Annotation NOT NULL in eine Nicht-Schlüsselspalte aufnehmen. Beispiel:

    ALTER TABLE Songwriters ALTER COLUMN Nickname STRING(MAX) NOT NULL;
    
  • Die Länge einer Spalte verringern. Beispiel:

    ALTER TABLE Songwriters ALTER COLUMN FirstName STRING(10);
    
  • BYTES in STRING ändern. Beispiel:

    ALTER TABLE Songwriters ALTER COLUMN OpaqueData STRING(MAX);
    
  • INT64/INT32 in ENUM ändern. Beispiel:

    ALTER TABLE Albums ALTER COLUMN Label googlesql.example.music.RecordLabel;
    
  • Vorhandene Werte aus der RecordLabel-Enum-Definition entfernen.

  • Commit-Zeitstempel für eine vorhandene TIMESTAMP Spalte aktivieren. Beispiel:

    ALTER TABLE Albums ALTER COLUMN LastUpdateTime SET OPTIONS (allow_commit_timestamp = true);
    
  • Diagnoseeinschränkung zu einer vorhandenen Tabelle hinzufügen

  • Gespeicherte generierte Spalte zu einer vorhandenen Tabelle hinzufügen

  • Neue Tabelle mit einem Fremdschlüssel erstellen.

  • Einer vorhandenen Tabelle einen Fremdschlüssel hinzufügen

Diese Schemaaktualisierungen schlagen fehl, wenn die zugrunde liegenden Daten den neuen Einschränkungen nicht entsprechen. Die Anweisung ALTER TABLE Songwriters ALTER COLUMN Nickname STRING(MAX) NOT NULL schlägt beispielsweise fehl, wenn ein Wert in der Spalte Nickname NULL ist, da die vorhandenen Daten nicht der NOT NULL-Einschränkung der neuen Definition entsprechen.

Die Datenvalidierung kann mehrere Minuten bis viele Stunden andauern. Die Dauer der Datenvalidierung hängt von folgenden Faktoren ab:

  • Größe des Datasets
  • Rechenkapazität der Instanz
  • Auslastung der Instanz

Einige Schemaaktualisierungen können das Verhalten von Anfragen an die Datenbank während der Schemaaktualisierung ändern. Wenn Sie beispielsweise NOT NULL zu einer Spalte hinzufügen, lehnt Spanner fast sofort Schreibvorgänge für neue Anfragen ab, die NULL für die Spalte verwenden. Sollte die neue Schemaaktualisierung aufgrund der Datenvalidierung letztendlich fehlschlagen, wurden Schreibvorgänge in einem gewissen Zeitraum blockiert, auch wenn sie vom alten Schema akzeptiert worden wären.

Sie können einen lang andauernden Datenvalidierungsprozess mit der projects.instances.databases.operations.cancel Methode oder mit gcloud spanner operationsabbrechen.

Während der Schemaaktualisierung erstellte Schemaversionen

Da Spanner mit Schemaversionierung arbeitet, können Schemas von großen Datenbanken ohne Ausfallzeit aktualisiert werden. Spanner behält die ältere Schemaversion bei, um Lesevorgänge zu unterstützen, während die Schemaaktualisierung verarbeitet wird. Anschließend erstellt Spanner eine oder mehrere neue Versionen des Schemas, um die Schemaaktualisierung zu verarbeiten. Jede Version enthält das Ergebnis einer Gruppe von Anweisungen in einer einzelnen atomaren Änderung.

Die Schemaversionen stimmen nicht zwangsläufig eins zu eins mit Batches von DDL-Anweisungen oder einzelnen DDL-Anweisungen überein. Manche einzelne DDL-Anweisungen führen zu mehreren Schemaversionen, beispielsweise die Indexerstellung für vorhandene Basistabellen oder Anweisungen, die eine Datenvalidierung erfordern. In anderen Fällen können mehrere DDL-Anweisungen in einer einzigen Version zusammengefasst sein. Alte Schemaversionen können erhebliche Server- und Speicherressourcen verbrauchen und werden aufbewahrt, bis sie abgelaufen bzw. nicht mehr erforderlich sind, um Lesevorgänge von älteren Datenversionen bereitzustellen.

In der folgenden Tabelle sehen Sie, wie lange es dauert, bis Spanner ein Schema aktualisiert.

Schemavorgang Geschätzte Dauer
CREATE TABLE Minuten
CREATE INDEX

Minuten bis Stunden, wenn die Basistabelle vor dem Index erstellt wird.

Minuten, wenn die Anweisung gleichzeitig mit der Anweisung CREATE TABLE für die Basistabelle ausgeführt wird.

DROP TABLE Minuten
DROP INDEX Minuten
ALTER TABLE ... ADD COLUMN Minuten
ALTER TABLE ... ALTER COLUMN

Minuten bis Stunden, wenn eine Validierung im Hintergrund erforderlich ist.

Minuten, wenn keine Validierung im Hintergrund erforderlich ist.

ALTER TABLE ... DROP COLUMN Minuten
ANALYZE

Je nach Datenbankgröße Minuten bis Stunden.

Änderungen des Datentyps und Änderungsstreams

Wenn Sie den Datentyp einer Spalte ändern, die von einem Änderungs stream überwacht wird, spiegelt das Feld column_types der relevanten nachfolgenden Änderungsstream datensätze den neuen Typ wider. Das gilt auch für die JSON-Daten old_values im Feld mods der Datensätze.

Die new_values des Felds mods eines Änderungsstreamdatensatzes stimmen immer mit dem aktuellen Typ einer Spalte überein. Das Ändern des Datentyps einer überwachten Spalte hat keine Auswirkungen auf Änderungsstreamdatensätze, die vor dieser Änderung erstellt wurden.

Im Sonderfall einer Änderung von BYTES in STRING validiert Spanner die alten Werte der Spalte im Rahmen der Schemaaktualisierung. Daher hat Spanner die alten Werte vom Typ BYTES sicher in Strings decodiert, bevor nachfolgende Änderungsstreamdatensätze geschrieben werden.