Daten mit Batchschreibvorgang ändern

Auf dieser Seite werden Spanner-Batchschreibanfragen beschrieben und wie Sie diese verwenden können um Ihre Spanner-Daten zu ändern.

Sie können Spanner-Batchschreibvorgänge zum Einfügen, Aktualisieren oder Löschen verwenden in Ihren Spanner-Tabellen arbeiten. Spanner Batch-Schreibvorgänge unterstützen Schreibvorgänge mit niedriger Latenz ohne Lesevorgang und geben Mutationen in Batches angewendet werden. Für Batchschreibvorgänge gruppieren Sie verwandten Mutationen zusammengehören und alle Mutationen in einer Gruppe ein Commit durchgeführt werden in kleinstmöglichen Schritten. Die gruppenübergreifenden Mutationen werden in einer nicht angegebenen Reihenfolge angewendet und sind unabhängig voneinander (nicht atomar). Cloud Spanner benötigt keine warten, bis alle Mutationen angewendet wurden, bevor eine Antwort gesendet wird. dass der Batch-Schreibvorgang teilweise fehlgeschlagene Vorgänge ermöglicht. Sie können auch mehrere Batch-Schreibvorgänge gleichzeitig ausführen. Weitere Informationen finden Sie unter Batch-Schreiben verwenden.

Anwendungsfälle

Die Batch-Schreibfunktion von Spanner ist besonders nützlich, wenn Sie eine große Anzahl von Schreibvorgängen ohne Lesevorgang bestätigen möchten, für alle Mutationen jedoch keine atomare Transaktion benötigen.

Wenn Sie Ihre DML-Anfragen in Batches zusammenfassen möchten, verwenden Sie Batch-DML. , um Ihre Spanner-Daten zu ändern. Weitere Informationen zur Unterschiede zwischen DML und Mutationen finden Sie unter Vergleich von DML und Mutationen.

Für einzelne Mutationsanfragen empfehlen wir die Verwendung einer Sperrungs-Lese-/Schreibtransaktion.

Beschränkungen

Für Spanner-Batchschreibvorgänge gelten die folgenden Einschränkungen:

  • Batch-Schreiben in Spanner ist nicht über die Google Cloud Console oder die Google Cloud CLI verfügbar. Es ist nur mit REST und RPC verfügbar APIs und die Spanner-Java-Clientbibliothek

  • Wiederholungsschutz wird beim Batchschreibvorgang nicht unterstützt. Es ist möglich, dass Mutationen und eine Mutation, die mehr als einmal angewendet wird, zu einem Fehler führen. Wenn beispielsweise eine Insert-Mutation wiedergegeben wird, kann der Fehler „Element ist bereits vorhanden“ auftreten. Wenn Sie in der Mutation generierte oder auf Commit-Zeitstempel basierende Schlüssel verwenden, kann es dazu führen, dass der Tabelle zusätzliche Zeilen hinzugefügt werden. Wir empfehlen, Ihre Schreibvorgänge so zu strukturieren, dass sie idempotent für um dieses Problem zu vermeiden.

  • Sie können eine abgeschlossene Batchschreibanfrage nicht rückgängig machen. Sie können in Bearbeitung befindliche Batch-Schreibanfrage. Wenn Sie einen laufenden Batchschreibvorgang abbrechen, für Mutationen in nicht abgeschlossenen Gruppen wird ein Rollback durchgeführt. Mutationen in abgeschlossenen Gruppen an die Datenbank übergeben werden.

  • Die maximale Größe einer Batch-Schreibanfrage entspricht dem Limit für eine Commit-Anfrage. Weitere Informationen finden Sie unter Limits für das Erstellen, Lesen, Aktualisieren und Löschen von Daten

Batch-Schreibvorgänge verwenden

Für Batchschreibvorgänge benötigen Sie die Berechtigung spanner.databases.write für der Datenbank, die Sie ändern möchten. Sie können Mutationen im Batch schreiben nicht in einem einzigen Aufruf mit einer REST atomar oder RPC API Anruf anfordern.

Sie sollten die folgenden Mutationstypen bei der Verwendung von Batchschreibvorgängen gruppieren:

  • Zeilen mit demselben Primärschlüsselpräfix in der übergeordneten und der untergeordneten Datei werden eingefügt. Tabellen.
  • Zeilen mit einer Fremdschlüsselbeziehung zwischen den Tabellen in Tabellen einfügen.
  • Andere Arten verwandter Mutationen, abhängig von Ihrem Datenbankschema und Anwendungslogik.

Sie können auch die Spanner-Java-Clientbibliothek für Batch-Write-Vorgänge verwenden. Im folgenden Codebeispiel wird die Tabelle Singers mit neuen Zeilen aktualisiert.

Java


import com.google.api.gax.rpc.ServerStream;
import com.google.cloud.spanner.DatabaseClient;
import com.google.cloud.spanner.DatabaseId;
import com.google.cloud.spanner.Mutation;
import com.google.cloud.spanner.MutationGroup;
import com.google.cloud.spanner.Options;
import com.google.cloud.spanner.Spanner;
import com.google.cloud.spanner.SpannerOptions;
import com.google.common.collect.ImmutableList;
import com.google.rpc.Code;
import com.google.spanner.v1.BatchWriteResponse;

public class BatchWriteAtLeastOnceSample {

  /***
   * Assume DDL for the underlying database:
   * <pre>{@code
   *   CREATE TABLE Singers (
   *     SingerId   INT64 NOT NULL,
   *     FirstName  STRING(1024),
   *     LastName   STRING(1024),
   *   ) PRIMARY KEY (SingerId)
   *
   *   CREATE TABLE Albums (
   *     SingerId     INT64 NOT NULL,
   *     AlbumId      INT64 NOT NULL,
   *     AlbumTitle   STRING(1024),
   *   ) PRIMARY KEY (SingerId, AlbumId),
   *   INTERLEAVE IN PARENT Singers ON DELETE CASCADE
   * }</pre>
   */

  private static final MutationGroup MUTATION_GROUP1 =
      MutationGroup.of(
          Mutation.newInsertOrUpdateBuilder("Singers")
              .set("SingerId")
              .to(16)
              .set("FirstName")
              .to("Scarlet")
              .set("LastName")
              .to("Terry")
              .build());
  private static final MutationGroup MUTATION_GROUP2 =
      MutationGroup.of(
          Mutation.newInsertOrUpdateBuilder("Singers")
              .set("SingerId")
              .to(17)
              .set("FirstName")
              .to("Marc")
              .build(),
          Mutation.newInsertOrUpdateBuilder("Singers")
              .set("SingerId")
              .to(18)
              .set("FirstName")
              .to("Catalina")
              .set("LastName")
              .to("Smith")
              .build(),
          Mutation.newInsertOrUpdateBuilder("Albums")
              .set("SingerId")
              .to(17)
              .set("AlbumId")
              .to(1)
              .set("AlbumTitle")
              .to("Total Junk")
              .build(),
          Mutation.newInsertOrUpdateBuilder("Albums")
              .set("SingerId")
              .to(18)
              .set("AlbumId")
              .to(2)
              .set("AlbumTitle")
              .to("Go, Go, Go")
              .build());

  static void batchWriteAtLeastOnce() {
    // TODO(developer): Replace these variables before running the sample.
    final String projectId = "my-project";
    final String instanceId = "my-instance";
    final String databaseId = "my-database";
    batchWriteAtLeastOnce(projectId, instanceId, databaseId);
  }

  static void batchWriteAtLeastOnce(String projectId, String instanceId, String databaseId) {
    try (Spanner spanner =
        SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) {
      DatabaseId dbId = DatabaseId.of(projectId, instanceId, databaseId);
      final DatabaseClient dbClient = spanner.getDatabaseClient(dbId);

      // Creates and issues a BatchWrite RPC request that will apply the mutation groups
      // non-atomically and respond back with a stream of BatchWriteResponse.
      ServerStream<BatchWriteResponse> responses =
          dbClient.batchWriteAtLeastOnce(
              ImmutableList.of(MUTATION_GROUP1, MUTATION_GROUP2),
              Options.tag("batch-write-tag"));

      // Iterates through the results in the stream response and prints the MutationGroup indexes,
      // commit timestamp and status.
      for (BatchWriteResponse response : responses) {
        if (response.getStatus().getCode() == Code.OK_VALUE) {
          System.out.printf(
              "Mutation group indexes %s have been applied with commit timestamp %s",
              response.getIndexesList(), response.getCommitTimestamp());
        } else {
          System.out.printf(
              "Mutation group indexes %s could not be applied with error code %s and "
                  + "error message %s", response.getIndexesList(),
              Code.forNumber(response.getStatus().getCode()), response.getStatus().getMessage());
        }
      }
    }
  }
}

Nächste Schritte