Von PostgreSQL zu Spanner migrieren (GoogleSQL-Dialekt)

Auf dieser Seite finden Sie eine Anleitung zum Migrieren einer Open-Source-PostgreSQL-Datenbank zu Spanner.

Die Migration umfasst die folgenden Aufgaben:

  • PostgreSQL-Schema einem Spanner-Schema zuordnen
  • Spanner-Instanz, -Datenbank und -Schema erstellen
  • Anwendung für die Arbeit mit der Spanner-Datenbank refaktorieren
  • Daten migrieren
  • Neues System überprüfen und in Produktionsstatus übergehen

Auf dieser Seite finden Sie außerdem einige Beispielschemas, die Tabellen aus der PostgreSQL-Datenbank MusicBrainz verwenden.

PostgreSQL-Schema Spanner zuordnen

Beim Verschieben einer Datenbank von PostgreSQL zu Spanner müssen Sie zuerst ermitteln, welche Schemaänderungen Sie vornehmen müssen. Erstellen Sie dafür mit pg_dump DDL-Anweisungen (Data Definition Language, Datendefinitionssprache), die Objekte in der PostgreSQL-Datenbank definieren. Verändern Sie dann die Anweisungen, wie in den folgenden Abschnitten beschrieben. Nachdem Sie die DDL-Anweisungen aktualisiert haben, erstellen Sie damit die Datenbank in einer Spanner-Instanz.

Datentypen

In der folgenden Tabelle wird beschrieben, wie PostgreSQL-Datentypen den Spanner-Datentypen zugeordnet werden. Aktualisieren Sie die Datentypen in Ihren DDL-Anweisungen von PostgreSQL-Datentypen in Spanner-Datentypen.

PostgreSQL Spanner
Bigint

int8

INT64
Bigserial

serial8

INT64
bit [ (n) ] ARRAY<BOOL>
bit varying [ (n) ]

varbit [ (n) ]

ARRAY<BOOL>
Boolean

bool

BOOL
box ARRAY<FLOAT64>
bytea BYTES
character [ (n) ]

char [ (n) ]

STRING
character varying [ (n) ]

varchar [ (n) ]

STRING
cidr STRING mit der standardmäßigen CIDR-Schreibweise
circle ARRAY<FLOAT64>
date DATE
double precision

float8

FLOAT64
inet STRING
Integer

int

int4

INT64
interval[ fields ] [ (p) ] INT64, wenn der Wert in Millisekunden gespeichert wird, oder STRING, wenn der Wert in einem anwendungsdefinierten Intervallformat gespeichert wird.
json STRING
jsonb JSON
line ARRAY<FLOAT64>
lseg ARRAY<FLOAT64>
macaddr STRING mit der standardmäßigen Schreibweise der MAC-Adresse
money INT64 oder STRING für Zahlen mit beliebiger Genauigkeit.
numeric [ (p, s) ]

decimal [ (p, s) ]

In PostgreSQL unterstützen die Datentypen NUMERIC und DECIMAL eine Genauigkeit von bis zu 217 Stellen sowie 214–1 gemäß der Skalierung, wie in der Spaltendeklaration definiert.

Der Spanner-Datentyp NUMERIC unterstützt eine Genauigkeit von bis zu 38 Stellen und eine Skalierung mit 9 Dezimalstellen.

Wenn Sie eine höhere Genauigkeit benötigen, finden Sie unter Numerische Daten mit beliebiger Genauigkeit speichern alternative Mechanismen.
path ARRAY<FLOAT64>
pg_lsn Dieser Datentyp ist PostgreSQL-spezifisch, daher gibt es kein Spanner-Äquivalent.
point ARRAY<FLOAT64>
polygon ARRAY<FLOAT64>
Real

float4

FLOAT64
Smallint

int2

INT64
Smallserial

serial2

INT64
Serial

serial4

INT64
text STRING
time [ (p) ] [ without time zone ] STRING, mit der Schreibweise HH:MM:SS.sss
time [ (p) ] with time zone

timetz

STRING, mit der Schreibweise HH:MM:SS.sss+ZZZZ Alternativ kann diese in zwei Spalten aufgeteilt werden. Dabei hat die eine den Typ TIMESTAMP und die andere enthält die Zeitzone.
timestamp [ (p) ] [ without time zone ] Kein Äquivalent. Kann nach Belieben als STRING oder TIMESTAMP gespeichert werden.
timestamp [ (p) ] with time zone

timestamptz

TIMESTAMP
tsquery Kein Äquivalent. Definieren Sie stattdessen einen Speichermechanismus in der Anwendung.
tsvector Kein Äquivalent. Definieren Sie stattdessen einen Speichermechanismus in der Anwendung.
txid_snapshot Kein Äquivalent. Definieren Sie stattdessen einen Speichermechanismus in der Anwendung.
uuid STRING oder BYTES
xml STRING

Primärschlüssel

Vermeiden Sie bei Tabellen in Ihrer Spanner-Datenbank, an die Sie häufig anhängen, Primärschlüssel, die kontinuierlich zu- oder abnehmen, da dies bei Schreibvorgängen Hotspots verursacht. Ändern Sie stattdessen die DDL-Anweisungen CREATE TABLE so, dass sie unterstützte Primärschlüsselstrategien verwenden. Wenn Sie eine PostgreSQL-Funktion wie einen UUID Datentyp oder -funktion, SERIAL Datentypen, IDENTITY Spalten oder Sequenzen verwenden, können Sie die von uns empfohlenen automatisch generierten Schlüsselmigrationsstrategien verwenden.

Nachdem Sie Ihren Primärschlüssel festgelegt haben, können Sie keine Primärschlüsselspalte hinzufügen oder entfernen und auch keinen Primärschlüsselwert später ändern, ohne die Tabelle zu löschen und neu zu erstellen. Weitere Informationen zum Festlegen des Primärschlüssels finden Sie unter Schema und Datenmodell – Primärschlüssel.

Während der Migration ist es möglicherweise erforderlich, dass Sie einige vorhandene kontinuierlich steigende Ganzzahlschlüssel beibehalten. Wenn eine Aufbewahrung dieser Schlüssel in einer Tabelle erforderlich ist, die häufig aktualisiert wird und viele Vorgänge für diese Schlüssel enthält, können Sie Hotspots vermeiden. Stellen Sie dazu dem vorhandenen Schlüssel eine Pseudogenerierung zufälliger Zahlen voran. Dieses Verfahren führt dazu, dass Spanner die Zeilen neu verteilt. Weitere Informationen zur Verwendung dieses Ansatzes finden Sie unter Das sollten Datenbankadministratoren über Spanner wissen, Teil 1: Schlüssel und Indexe.

Fremdschlüssel und referenzielle Integrität

Weitere Informationen zur Unterstützung von Fremdschlüsseln in Spanner

Indexe

PostgreSQL-B-Tree-Indexe ähneln den sekundären Indexen in Spanner. In einer Spanner-Datenbank verwenden Sie sekundäre Indexe, um häufig gesuchte Spalten zu indexieren, um die Leistung zu verbessern, und um in Ihren Tabellen angegebene UNIQUE-Einschränkungen zu ersetzen. Wenn die PostgreSQL-DDL beispielsweise folgende Anweisung enthält:

 CREATE TABLE customer (
    id CHAR (5) PRIMARY KEY,
    first_name VARCHAR (50),
    last_name VARCHAR (50),
    email VARCHAR (50) UNIQUE
 );

Sie würden diese Anweisung in Ihrer Spanner-DDL verwenden:

CREATE TABLE customer (
   id STRING(5),
   first_name STRING(50),
   last_name STRING(50),
   email STRING(50)
   ) PRIMARY KEY (id);

CREATE UNIQUE INDEX customer_emails ON customer(email);

Wenn Sie die Indexe in PostgreSQL-Tabellen suchen, führen Sie den Meta-Befehl \di in psql aus.

Nachdem Sie die benötigten Indexe ermittelt haben, fügen Sie CREATE INDEX-Anweisungen hinzu, um sie zu erstellen. Folgen Sie der Anleitung unter Indexe erstellen.

Spanner implementiert Indexe als Tabellen, sodass das Indexieren von kontinuierlich steigenden Spalten (wie solchen mit TIMESTAMP-Daten) einen Hotspot verursachen kann. Weitere Informationen zu Methoden zur Vermeidung von Hotspots finden Sie unter Das sollten Datenbankadministratoren über Spanner wissen, Teil 1: Schlüssel und Indexe.

Einschränkungen prüfen

Weitere Informationen zur Unterstützung von CHECK-Einschränkungen in Spanner

Andere Datenbankobjekte

Es ist erforderlich, dass Sie die Funktionen der folgenden Objekte in der Anwendungslogik erstellen:

  • Ansichten
  • Trigger
  • Gespeicherte Prozeduren
  • Nutzerdefinierte Funktionen (UDFs)
  • Spalten mit serial-Datentypen als Sequenzgeneratoren

Beachten Sie bei der Migration dieser Funktionen in die Anwendungslogik die folgenden Hinweise:

Spanner-Instanz erstellen

Nachdem Sie die DDL-Anweisungen so aktualisiert haben, dass sie den Anforderungen des Spanner-Schemas entsprechen, erstellen Sie damit Ihre Datenbank in Spanner.

  1. Erstellen Sie eine Spanner-Instanz. Folgen Sie der Anleitung unter Instanzen, um die korrekte regionale Konfiguration und die Rechenkapazität zu ermitteln, die Ihre Leistungsziele unterstützen.

  2. Erstellen Sie die Datenbank mit der Google Cloud Console oder dem gcloud-Befehlszeilentool:

Console

  1. Zur Seite "Instanzen"
  2. Klicken Sie auf den Namen der Instanz, in der Sie die Beispieldatenbank erstellen möchten, um die Seite mit den Instanzdetails zu öffnen.
  3. Klicken Sie auf Datenbank erstellen.
  4. Geben Sie einen Namen für die Datenbank ein und klicken Sie auf Weiter.
  5. Schalten Sie im Abschnitt Datenbankschema definieren das Steuerelement Als Text bearbeiten ein.
  6. Kopieren Sie Ihre DDL-Anweisungen und fügen Sie sie in das Feld DDL-Anweisungen ein.
  7. Klicken Sie auf Erstellen.

gcloud

  1. Installieren Sie die gcloud CLI.
  2. Erstellen Sie die Datenbank mit dem Befehl gcloud spanner databases create:
    gcloud spanner databases create DATABASE_NAME --instance=INSTANCE_NAME
    --ddl='DDL1' --ddl='DDL2'
    
  • DATABASE_NAME ist der Name der Datenbank.
  • INSTANCE_NAME ist die von Ihnen erstellte Spanner-Instanz.
  • DDLn sind Ihre geänderten DDL-Anweisungen.

Folgen Sie nach dem Erstellen der Datenbank der Anleitung unter IAM-Rollen anwenden, um Nutzerkonten zu erstellen und der Spanner-Instanz und -Datenbank Berechtigungen zu erteilen.

Anwendungen und Datenzugriffsebenen refaktorieren

Zusätzlich zum Code, der zum Ersetzen der vorhergehenden Datenbankobjekte erforderlich ist, ist es notwendig, dass Sie Anwendungslogik zur Verarbeitung der folgenden Funktionen hinzufügen:

  • Hash-Primärschlüssel für Schreibvorgänge, für Tabellen mit hohen Schreibraten für sequenzielle Schlüssel.
  • Daten validieren, die noch nicht durch CHECK-Einschränkungen abgedeckt sind.
  • Referenzielle, noch nicht durch Fremdschlüssel, Tabellenverschränkungen oder Anwendungslogik abgedeckte Integritätsprüfungen, einschließlich Funktionen, die von Triggern im PostgreSQL-Schema verarbeitet werden.

Wir empfehlen bei der Refaktorierung den folgenden Prozess:

  1. Suchen Sie nach dem gesamten auf die Datenbank zugreifenden Anwendungscode und wandeln Sie ihn in ein einzelnes Modul oder eine Bibliothek um. So wissen Sie genau, welcher Code auf die Datenbank zugreift und welcher Code geändert werden muss.
  2. Schreiben Sie Code, der Lese- und Schreibvorgänge auf der Spanner-Instanz ausführt und parallele Funktionalität zum ursprünglichen Code bietet, der Lese- und Schreibvorgänge in PostgreSQL ausführt. Aktualisieren Sie bei Schreibvorgängen die gesamte Zeile, nicht nur die Spalten, die geändert wurden, um sicherzustellen, dass die Daten in Spanner mit denen in PostgreSQL identisch sind.
  3. Schreiben Sie Code, der die Funktionalität der Datenbankobjekte und -funktionen ersetzt, die in Spanner nicht verfügbar sind.

Daten migrieren

Nachdem Sie die Spanner-Datenbank erstellt und den Anwendungscode refaktoriert haben, können Sie Ihre Daten zu Spanner migrieren.

  1. Sichern Sie mit dem PostgreSQL-Befehl COPY Daten in CSV-Dateien.
  2. Laden Sie die CSV-Dateien in Cloud Storage hoch.

    1. Erstellen Sie einen Cloud Storage-Bucket.
    2. Klicken Sie in der Cloud Storage-Konsole auf den Bucket-Namen, um den Bucket-Browser zu öffnen.
    3. Klicken Sie auf Dateien hochladen.
    4. Gehen Sie zum Verzeichnis mit den CSV-Dateien und wählen Sie die Dateien aus.
    5. Klicken Sie auf Öffnen.
  3. Erstellen Sie eine Anwendung zum Importieren von Daten in Spanner. Diese Anwendung kann Dataflow oder die Clientbibliotheken direkt verwenden. Folgen Sie der Anleitung unter Best Practices für das Laden im Bulk, um die beste Leistung zu erzielen.

Tests

Testen Sie alle Anwendungsfunktionen mit der Spanner-Instanz, um zu prüfen, ob sie wie erwartet funktionieren. Führen Sie Arbeitslasten auf Produktionsebene aus, damit die Leistung Ihren Anforderungen tatsächlich entspricht. Aktualisieren Sie die Rechenkapazität nach Bedarf, damit Sie Ihre Leistungsziele erreichen können.

Auf das neue System umsteigen

Nachdem Sie die ersten Anwendungstests abgeschlossen haben, aktivieren Sie das neue System mit einem der folgenden Prozesse. Die Offline-Migration ist die einfachste Methode für die Migration. Bei diesem Ansatz ist Ihre Anwendung jedoch für einen bestimmten Zeitraum nicht verfügbar und es wird kein Rollback-Pfad bereitgestellt, falls später Datenprobleme auftreten sollten. So führen Sie eine Offline-Migration durch:

  1. Löschen Sie alle Daten in der Spanner-Datenbank.
  2. Fahren Sie die Anwendung herunter, die die PostgreSQL-Datenbank als Ziel hat.
  3. Exportieren Sie alle Daten aus der PostgreSQL-Datenbank und importieren Sie sie in die Spanner-Datenbank, wie unter Daten migrieren beschrieben.
  4. Starten Sie die Anwendung, die auf die Spanner-Datenbank ausgerichtet ist.

    Datenfluss der Offline-Migration

Eine Live-Migration ist möglich und erfordert umfangreiche Änderungen an Ihrer Anwendung zur Unterstützung der Migration.

Beispiele für Schemamigration

Diese Beispiele zeigen Anweisungen CREATE TABLE für mehrere Tabellen in dem PostgreSQL-DatenbankschemaMusicBrainz. Jedes Beispiel enthält sowohl das PostgreSQL-Schema als auch das Spanner-Schema.

Tabelle "artist_credit"

PostgreSQL-Version:

CREATE TABLE artist_credit (
  id SERIAL,
  name VARCHAR NOT NULL,
  artist_count SMALLINT NOT NULL,
  ref_count INTEGER DEFAULT 0,
  created TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

Spanner-Version:

CREATE TABLE artist_credit (
  hashed_id STRING(4),
  id INT64,
  name STRING(MAX) NOT NULL,
  artist_count INT64 NOT NULL,
  ref_count INT64,
  created TIMESTAMP OPTIONS (
     allow_commit_timestamp = true
  ),
) PRIMARY KEY(hashed_id, id);

Tabelle "recording"

PostgreSQL-Version:

CREATE TABLE recording (
  id SERIAL,
  gid UUID NOT NULL,
  name VARCHAR NOT NULL,
  artist_credit INTEGER NOT NULL, -- references artist_credit.id
  length INTEGER CHECK (length IS NULL OR length > 0),
  comment VARCHAR(255) NOT NULL DEFAULT '',
  edits_pending INTEGER NOT NULL DEFAULT 0 CHECK (edits_pending >= 0),
  last_updated TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
  video BOOLEAN NOT NULL DEFAULT FALSE
);

Spanner-Version:

CREATE TABLE recording (
  hashed_id STRING(36),
  id INT64,
  gid STRING(36) NOT NULL,
  name STRING(MAX) NOT NULL,
  artist_credit_hid STRING(36) NOT NULL,
  artist_credit_id INT64 NOT NULL,
  length INT64,
  comment STRING(255) NOT NULL,
  edits_pending INT64 NOT NULL,
  last_updated TIMESTAMP OPTIONS (
     allow_commit_timestamp = true
  ),
  video BOOL NOT NULL,
) PRIMARY KEY(hashed_id, id);

Tabelle "recording-alias"

PostgreSQL-Version:

CREATE TABLE recording_alias (
  id SERIAL, --PK
  recording INTEGER NOT NULL, -- references recording.id
  name VARCHAR NOT NULL,
  locale TEXT,
  edits_pending INTEGER NOT NULL DEFAULT 0 CHECK (edits_pending >=0),
  last_updated TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
  type INTEGER, -- references recording_alias_type.id
  sort_name VARCHAR NOT NULL,
  begin_date_year SMALLINT,
  begin_date_month SMALLINT,
  begin_date_day SMALLINT,
  end_date_year SMALLINT,
  end_date_month SMALLINT,
  end_date_day SMALLINT,
  primary_for_locale BOOLEAN NOT NULL DEFAULT false,
  ended BOOLEAN NOT NULL DEFAULT FALSE
  -- CHECK constraint skipped for brevity
);

Spanner-Version:

CREATE TABLE recording_alias (
  hashed_id STRING(36)  NOT NULL,
  id INT64  NOT NULL,
  alias_id INT64,
  name STRING(MAX)  NOT NULL,
  locale STRING(MAX),
  edits_pending INT64  NOT NULL,
  last_updated TIMESTAMP NOT NULL OPTIONS (
     allow_commit_timestamp = true
  ),
  type INT64,
  sort_name STRING(MAX)  NOT NULL,
  begin_date_year INT64,
  begin_date_month INT64,
  begin_date_day INT64,
  end_date_year INT64,
  end_date_month INT64,
  end_date_day INT64,
  primary_for_locale BOOL NOT NULL,
  ended BOOL NOT NULL,
) PRIMARY KEY(hashed_id, id, alias_id),
 INTERLEAVE IN PARENT recording ON DELETE NO ACTION;