Modificare i dati utilizzando la scrittura batch

Questa pagina descrive le richieste di scrittura batch di Spanner e come puoi utilizzarle per modificare i dati di Spanner.

Puoi utilizzare la scrittura batch di Spanner per inserire, aggiornare o eliminare più righe nelle tabelle di Spanner. La scrittura batch di Spanner supporta le scritture a bassa latenza senza un'operazione di lettura e restituisce le risposte man mano che le mutazioni vengono applicate in batch. Per utilizzare la scrittura batch, raggruppa le mutazioni correlate e tutte le mutazioni in un gruppo vengono eseguite in modo atomico. Le mutazioni tra i gruppi vengono applicate in un ordine non specificato e sono indipendenti l'una dall'altra (non atomiche). Spanner non deve attendere l'applicazione di tutte le mutazioni prima di inviare una risposta, il che significa che la scrittura batch consente un errore parziale. Puoi anche eseguire più scritture batch contemporaneamente. Per ulteriori informazioni, consulta la sezione Come utilizzare la scrittura batch.

Casi d'uso

La scrittura batch di Spanner è particolarmente utile se vuoi eseguire il commit di un numero elevato di scritture senza un'operazione di lettura, ma non richiedi una transazione atomica per tutte le mutazioni.

Se vuoi eseguire il batch delle richieste DML, utilizza DML batch per modificare i dati di Spanner. Per ulteriori informazioni sulle differenze tra DML e mutazioni, consulta Confronto tra DML e mutazioni.

Per le richieste di singola mutazione, ti consigliamo di utilizzare una transazione di lettura-scrittura con blocco.

Limitazioni

La scrittura batch di Spanner presenta le seguenti limitazioni:

  • La scrittura batch di Spanner non è disponibile tramite la Google Cloud console o Google Cloud CLI. È disponibile solo tramite le API REST e RPC e le librerie client di Spanner.

  • La protezione dalla riproduzione non è supportata tramite la scrittura batch. È possibile che le mutazioni vengano applicate più di una volta e una mutazione applicata più di una volta potrebbe causare un errore. Ad esempio, se viene riprodotta una mutazione di inserimento, potrebbe generare un errore di esistenza o, se utilizzi chiavi basate su timestamp di commit o generate nella mutazione, potrebbero essere aggiunte altre righe alla tabella. Ti consigliamo di strutturare le scritture in modo che siano idempotenti per evitare questo problema.

  • Non puoi eseguire il rollback di una richiesta di scrittura batch completata. Puoi annullare una richiesta di scrittura batch in corso. Se annulli una scrittura batch in corso, viene eseguito il rollback delle mutazioni nei gruppi non completati. Le mutazioni nei gruppi completati vengono eseguite nel database.

  • La dimensione massima per una richiesta di scrittura batch è la stessa del limite per una richiesta di commit. Per ulteriori informazioni, consulta Limiti per la creazione, la lettura, l'aggiornamento e l'eliminazione dei dati.

Come utilizzare la scrittura batch

Per utilizzare la scrittura batch, devi disporre dell'autorizzazione spanner.databases.write per il database che vuoi modificare. Puoi eseguire il batch delle mutazioni di scrittura in modo non atomico in una singola chiamata utilizzando una chiamata di richiesta API REST o RPC.

Quando utilizzi la scrittura batch, devi raggruppare i seguenti tipi di mutazione:

  • Inserimento di righe con lo stesso prefisso della chiave primaria nelle tabelle padre e figlio.
  • Inserimento di righe nelle tabelle con una relazione di chiave esterna tra le tabelle.
  • Altri tipi di mutazioni correlate a seconda dello schema del database e della logica dell'applicazione.

Puoi anche eseguire la scrittura batch utilizzando le librerie client di Spanner. Il seguente esempio di codice aggiorna la tabella Singers con nuove righe.

Librerie client

C++

namespace spanner = ::google::cloud::spanner;
// Use upserts as mutation groups are not replay protected.
auto commit_results = client.CommitAtLeastOnce({
    // group #0
    spanner::Mutations{
        spanner::InsertOrUpdateMutationBuilder(
            "Singers", {"SingerId", "FirstName", "LastName"})
            .EmplaceRow(16, "Scarlet", "Terry")
            .Build(),
    },
    // group #1
    spanner::Mutations{
        spanner::InsertOrUpdateMutationBuilder(
            "Singers", {"SingerId", "FirstName", "LastName"})
            .EmplaceRow(17, "Marc", "")
            .EmplaceRow(18, "Catalina", "Smith")
            .Build(),
        spanner::InsertOrUpdateMutationBuilder(
            "Albums", {"SingerId", "AlbumId", "AlbumTitle"})
            .EmplaceRow(17, 1, "Total Junk")
            .EmplaceRow(18, 2, "Go, Go, Go")
            .Build(),
    },
});
for (auto& commit_result : commit_results) {
  if (!commit_result) throw std::move(commit_result).status();
  std::cout << "Mutation group indexes [";
  for (auto index : commit_result->indexes) std::cout << " " << index;
  std::cout << " ]: ";
  if (commit_result->commit_timestamp) {
    auto const& ts = *commit_result->commit_timestamp;
    std::cout << "Committed at " << ts.get<absl::Time>().value();
  } else {
    std::cout << commit_result->commit_timestamp.status();
  }
  std::cout << "\n";
}

C#

// Copyright 2026 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.


using Google.Cloud.Spanner.Data;
using Google.Rpc;
using Google.Cloud.Spanner.V1;
using Google.Protobuf.WellKnownTypes;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

public class BatchWriteAtLeastOnceAsyncSample
{
    public async Task BatchWriteAtLeastOnceAsync(string projectId, string