Ripristinare le tabelle eliminate

Questo documento descrive come ripristinare (o annullare l'eliminazione) di una tabella eliminata in BigQuery. Puoi ripristinare una tabella eliminata entro la finestra di spostamento cronologico specificata per il set di dati, incluse le eliminazioni esplicite e le eliminazioni implicite dovute alla scadenza della tabella. Puoi anche configurare la finestra di spostamento cronologico.

Per informazioni su come ripristinare un intero set di dati o snapshot eliminato, consulta le seguenti risorse:

La finestra di spostamento cronologico può avere una durata compresa tra due e sette giorni. Una volta trascorsa la finestra di spostamento cronologico, BigQuery fornisce un periodo di sicurezza in cui i dati eliminati vengono conservati automaticamente per altri sette giorni. Una volta trascorso il periodo di sicurezza, non è possibile ripristinare una tabella utilizzando alcun metodo, inclusa l'apertura di una ticket di assistenza.

Prima di iniziare

Assicurati di disporre delle autorizzazioni di Identity and Access Management (IAM) necessarie per ripristinare una tabella eliminata.

Ruoli obbligatori

Per ottenere le autorizzazioni necessarie per ripristinare una tabella eliminata, chiedi all'amministratore di concederti il ruolo IAM Utente BigQuery (roles/bigquery.user) nel progetto. Per saperne di più sulla concessione dei ruoli, consulta Gestisci l'accesso a progetti, cartelle e organizzazioni.

Potresti anche riuscire a ottenere le autorizzazioni richieste tramite i ruoli personalizzati o altri ruoli predefiniti.

Ripristinare una tabella

Puoi ripristinare una tabella dai dati storici copiando i dati storici in una nuova tabella. La copia dei dati storici funziona anche se la tabella è stata eliminata o è scaduta, a condizione che tu ripristini la tabella entro la durata della finestra di spostamento cronologico.

Quando ripristini una tabella dai dati storici, tag dalla tabella di origine non vengono copiati nella tabella di destinazione. Anche le informazioni sul partizionamento delle tabelle non vengono copiate nella tabella di destinazione. Per ricreare lo schema di partizionamento della tabella originale, puoi visualizzare la richiesta di creazione della tabella iniziale in Cloud Logging e utilizzare queste informazioni per partizionare la tabella ripristinata.

Puoi ripristinare una tabella eliminata ma ancora all'interno della finestra di spostamento cronologico copiandola in una nuova tabella utilizzando il decoratore temporale @<time>. Non puoi eseguire query su una tabella eliminata, anche se utilizzi un decoratore temporale. Devi prima ripristinarla.

Utilizza la seguente sintassi con il @<time> decoratore temporale:

  • tableid@TIME dove TIME è il numero di millisecondi trascorsi dall'epoca Unix.
  • tableid@-TIME_OFFSET dove TIME_OFFSET è l'offset relativo rispetto all'ora corrente, in millisecondi.
  • tableid@0: specifica i dati storici disponibili più vecchi.

Per ripristinare una tabella, seleziona una delle seguenti opzioni:

Console

Non puoi annullare l'eliminazione di una tabella utilizzando la Google Cloud console.

bq

  1. Nella Google Cloud console, attiva Cloud Shell.

    Attiva Cloud Shell

    Nella parte inferiore della Google Cloud console viene avviata una sessione di Cloud Shell e viene visualizzato un prompt della riga di comando. Cloud Shell è un ambiente shell con Google Cloud CLI già inclusa e installata e con valori già impostati per il progetto corrente. L'inizializzazione della sessione può richiedere alcuni secondi.

  2. Per ripristinare una tabella, determina innanzitutto un timestamp Unix di quando la tabella esisteva (in millisecondi). Puoi utilizzare il comando date di Linux per generare il timestamp Unix da un valore di timestamp normale:

    date -d '2023-08-04 16:00:34.456789Z' +%s000
    
  3. Quindi, utilizza il comando bq copy con il @<time> decoratore di spostamento cronologico per eseguire l'operazione di copia della tabella.

    Ad esempio, inserisci il seguente comando per copiare la tabella mydataset.mytable all'ora 1418864998000 in una nuova tabella mydataset.newtable.

    bq cp mydataset.mytable@1418864998000 mydataset.newtable
    

    (Facoltativo) Fornisci il flag --location e imposta il valore sulla tua località.

    Puoi anche specificare un offset relativo. Il seguente esempio copia la versione di una tabella di un'ora fa:

    bq cp mydataset.mytable@-3600000 mydataset.newtable
    

Vai

Prima di provare questo esempio, segui le istruzioni di configurazione di Go nella guida rapida di BigQuery per l'utilizzo delle librerie client. Per saperne di più, consulta la documentazione di riferimento dell'Go API BigQuery.

Per eseguire l'autenticazione in BigQuery, configura le Credenziali predefinite dell'applicazione. Per saperne di più, vedi Configura l'autenticazione per le librerie client.

import (
	"context"
	"fmt"
	"time"

	"cloud.google.com/go/bigquery"
)

// deleteAndUndeleteTable demonstrates how to recover a deleted table by copying it from a point in time
// that predates the deletion event.
func deleteAndUndeleteTable(projectID, datasetID, tableID string) error {
	// projectID := "my-project-id"
	// datasetID := "mydataset"
	// tableID := "mytable"
	ctx := context.Background()
	client, err := bigquery.NewClient(ctx, projectID)
	if err != nil {
		return fmt.Errorf("bigquery.NewClient: %v", err)
	}
	defer client.Close()

	ds := client.Dataset(datasetID)
	if _, err := ds.Table(tableID).Metadata(ctx); err != nil {
		return err
	}
	// Record the current time.  We'll use this as the snapshot time
	// for recovering the table.
	snapTime := time.Now()

	// "Accidentally" delete the table.
	if err := client.Dataset(datasetID).Table(tableID).Delete(ctx); err != nil {
		return err
	}

	// Construct the restore-from tableID using a snapshot decorator.
	snapshotTableID := fmt.Sprintf("%s@%d", tableID, snapTime.UnixNano()/1e6)
	// Choose a new table ID for the recovered table data.
	recoverTableID := fmt.Sprintf("%s_recovered", tableID)

	// Construct and run a copy job.
	copier := ds.Table(recoverTableID).CopierFrom(ds.Table(snapshotTableID))
	copier.WriteDisposition = bigquery.WriteTruncate
	job, err := copier.Run(ctx)
	if err != nil {
		return err
	}
	status, err := job.Wait(ctx)
	if err != nil {
		return err
	}
	if err := status.Err(); err != nil {
		return err
	}

	ds.Table(recoverTableID).Delete(ctx)
	return nil
}

Java

Prima di provare questo esempio, segui le istruzioni di configurazione Java nella guida rapida di BigQuery per l'utilizzo delle librerie client. Per saperne di più, consulta la documentazione di riferimento dell'API Java BigQuery.

Per eseguire l'autenticazione in BigQuery, configura le Credenziali predefinite dell'applicazione. Per saperne di più, vedi Configura l'autenticazione per le librerie client.

import com.google.cloud.bigquery.BigQuery;
import com.google.cloud.bigquery.BigQueryException;
import com.google.cloud.bigquery.BigQueryOptions;
import com.google.cloud.bigquery.CopyJobConfiguration;
import com.google.cloud.bigquery.Job;
import com.google.cloud.bigquery.JobInfo;
import com.google.cloud.bigquery.TableId;

// Sample to undeleting a table
public class UndeleteTable {

  public static void runUndeleteTable() {
    // TODO(developer): Replace these variables before running the sample.
    String datasetName = "MY_DATASET_NAME";
    String tableName = "MY_TABLE_TABLE";
    String recoverTableName = "MY_RECOVER_TABLE_TABLE";
    undeleteTable(datasetName, tableName, recoverTableName);
  }

  public static void undeleteTable(String datasetName, String tableName, String recoverTableName) {
    try {
      // Initialize client that will be used to send requests. This client only needs to be created
      // once, and can be reused for multiple requests.
      BigQuery bigquery = BigQueryOptions.getDefaultInstance().getService();

      // "Accidentally" delete the table.
      bigquery.delete(TableId.of(datasetName, tableName));

      // Record the current time.  We'll use this as the snapshot time
      // for recovering the table.
      long snapTime = System.currentTimeMillis();

      // Construct the restore-from tableID using a snapshot decorator.
      String snapshotTableId = String.format("%s@%d", tableName, snapTime);

      // Construct and run a copy job.
      CopyJobConfiguration configuration =
          CopyJobConfiguration.newBuilder(
                  // Choose a new table ID for the recovered table data.
                  TableId.of(datasetName, recoverTableName),
                  TableId.of(datasetName, snapshotTableId))
              .build();

      Job job = bigquery.create(JobInfo.of(configuration));
      job = job.waitFor();
      if (job.isDone() && job.getStatus().getError() == null) {
        System.out.println("Undelete table recovered successfully.");
      } else {
        System.out.println(
            "BigQuery was unable to copy the table due to an error: \n"
                + job.getStatus().getError());
        return;
      }
    } catch (BigQueryException | InterruptedException e) {
      System.out.println("Table not found. \n" + e.toString());
    }
  }
}

Node.js

Prima di provare questo esempio, segui le istruzioni di configurazione Node.js nella guida rapida di BigQuery per l'utilizzo delle librerie client. Per saperne di più, consulta la documentazione di riferimento dell'Node.js API BigQuery.

Per eseguire l'autenticazione in BigQuery, configura le Credenziali predefinite dell'applicazione. Per saperne di più, vedi Configura l'autenticazione per le librerie client.

// Import the Google Cloud client library
const {BigQuery} = require('@google-cloud/bigquery');
const bigquery = new BigQuery();

async function undeleteTable() {
  // Undeletes "my_table_to_undelete" from "my_dataset".

  /**
   * TODO(developer): Uncomment the following lines before running the sample.
   */
  // const datasetId = "my_dataset";
  // const tableId = "my_table_to_undelete";
  // const recoveredTableId = "my_recovered_table";

  /**
   * TODO(developer): Choose an appropriate snapshot point as epoch milliseconds.
   * For this example, we choose the current time as we're about to delete the
   * table immediately afterwards.
   */
  const snapshotEpoch = Date.now();

  // Delete the table
  await bigquery
    .dataset(datasetId)
    .table(tableId)
    .delete();

  console.log(`Table ${tableId} deleted.`);

  // Construct the restore-from table ID using a snapshot decorator.
  const snapshotTableId = `${tableId}@${snapshotEpoch}`;

  // Construct and run a copy job.
  await bigquery
    .dataset(datasetId)
    .table(snapshotTableId)
    .copy(bigquery.dataset(datasetId).table(recoveredTableId));

  console.log(
    `Copied data from deleted table ${tableId} to ${recoveredTableId}`
  );
}

Python

Prima di provare questo esempio, segui le istruzioni di configurazione di Python nella guida rapida di BigQuery per l'utilizzo delle librerie client. Per saperne di più, consulta la documentazione di riferimento dell'API PythonBigQuery.

Per eseguire l'autenticazione in BigQuery, configura le Credenziali predefinite dell'applicazione. Per saperne di più, vedi Configura l'autenticazione per le librerie client.

import time

from google.cloud import bigquery

# Construct a BigQuery client object.
client = bigquery.Client()

# TODO(developer): Choose a table to recover.
# table_id = "your-project.your_dataset.your_table"

# TODO(developer): Choose a new table ID for the recovered table data.
# recovered_table_id = "your-project.your_dataset.your_table_recovered"

# TODO(developer): Choose an appropriate snapshot point as epoch
# milliseconds. For this example, we choose the current time as we're about
# to delete the table immediately afterwards.
snapshot_epoch = int(time.time() * 1000)

# ...

# "Accidentally" delete the table.
client.delete_table(table_id)  # Make an API request.

# Construct the restore-from table ID using a snapshot decorator.
snapshot_table_id = "{}@{}".format(table_id, snapshot_epoch)

# Construct and run a copy job.
job = client.copy_table(
    snapshot_table_id,
    recovered_table_id,
    # Must match the source and destination tables location.
    location="US",
)  # Make an API request.

job.result()  # Wait for the job to complete.

print(
    "Copied data from deleted table {} to {}".format(table_id, recovered_table_id)
)

Se prevedi di voler ripristinare una tabella in un secondo momento rispetto a quanto consentito dalla finestra di spostamento cronologico, crea uno snapshot della tabella. Per saperne di più, vedi Introduzione agli snapshot delle tabelle.

Non puoi ripristinare direttamente una visualizzazione logica. Per saperne di più, vedi Ripristinare una visualizzazione.

Identificare quando è stata eliminata una tabella

Utilizza il seguente filtro in Esplora log nella Google Cloud console per identificare la voce di audit che mostra la scadenza o l'eliminazione di una tabella specifica:

resource.type="bigquery_resource"
protoPayload.resourceName="projects/PROJECT_ID/datasets/DATASET_ID/tables/TABLE_ID"
(protoPayload.methodName="google.cloud.bigquery.v2.TableService.DeleteTable" OR protoPayload.methodName="tableservice.delete" OR protoPayload.serviceData.jobCompletedEvent.job.jobConfiguration.query.statementType="DROP_TABLE" OR protoPayload.methodName="InternalTableExpired")

Sostituisci quanto segue:

  • PROJECT_ID: il tuo ID progetto.
  • DATASET_ID: l'ID del set di dati che conteneva la tabella.
  • TABLE_ID: l'ID della tabella eliminata.

In alternativa, utilizza il seguente filtro per trovare la scadenza o l'eliminazione del set di dati che conteneva la tabella:

resource.type="bigquery_dataset"
protoPayload.resourceName="projects/PROJECT_ID/datasets/DATASET_ID"
(protoPayload.methodName="google.cloud.bigquery.v2.DatasetService.DeleteDataset" OR protoPayload.methodName="datasetservice.delete")

Sostituisci quanto segue:

  • PROJECT_ID: il tuo ID progetto.
  • DATASET_ID: l'ID del set di dati che conteneva la tabella.

Identificare la causa dell'eliminazione della tabella

Puoi utilizzare la INFORMATION_SCHEMA.TABLE_STORAGE visualizzazione per determinare come è stata eliminata una tabella.

La visualizzazione INFORMATION_SCHEMA.TABLE_STORAGE contiene informazioni sulle tabelle correnti e sulle tabelle eliminate all'interno della finestra di spostamento cronologico. Se una tabella è stata eliminata, la colonna table_deletion_time contiene il timestamp di eliminazione e la colonna table_deletion_reason contiene il metodo di eliminazione.

Per determinare il motivo per cui una tabella è stata eliminata, esegui una query sulla visualizzazione INFORMATION_SCHEMA.TABLE_STORAGE:

SELECT
  table_name,
  deleted,
  table_deletion_time,
  table_deletion_reason
FROM
  `PROJECT_ID`.`region-REGION`.INFORMATION_SCHEMA.TABLE_STORAGE
WHERE
  table_schema = "DATASET_ID"
  AND table_name = "TABLE_ID"

Sostituisci le seguenti variabili:

  • PROJECT_ID: il tuo ID progetto.
  • REGION: la regione del set di dati che conteneva la tabella.
  • DATASET_ID: l'ID del set di dati che conteneva la tabella.
  • TABLE_ID: l'ID della tabella eliminata.

La colonna table_deletion_reason spiega perché la tabella è stata eliminata:

  • TABLE_EXPIRATION: la tabella è stata eliminata dopo l'ora di scadenza impostata.
  • DATASET_DELETION: il set di dati a cui apparteneva la tabella è stato eliminato da un utente.
  • USER_DELETED: la tabella è stata eliminata da un utente.

Risolvere i problemi di recupero delle tabelle

Eseguire query sulla tabella eliminata utilizzando un timestamp nel passato

Non puoi ripristinare i dati della tabella eseguendo query su una tabella eliminata in passato utilizzando un decoratore di timestamp o utilizzando FOR SYSTEM_TIME AS OF per salvare il risultato in una tabella di destinazione. L'utilizzo di uno di questi metodi genera il seguente errore:

Not found: Table myproject:mydataset.table was not found in location LOCATION

In alternativa, per copiare la tabella, segui i passaggi descritti in Ripristinare una tabella.

Errore: VPC Service Controls: Request is prohibited by organization's policy

Quando tenti di eseguire il comando di copia da Google Cloud Shell, potresti riscontrare un errore simile al seguente:

BigQuery error in cp operation: VPC Service Controls: Request is prohibited by organization's policy

L'utilizzo di Cloud Shell dalla Google Cloud console con VPC SC non è supportato, perché viene trattato come una richiesta al di fuori dei perimetri di servizio e l'accesso ai dati protetti da Controlli di servizio VPC viene negato. Per risolvere questo problema, avvia e connettiti a Cloud Shell localmente con Google Cloud CLI.

Errore: Latest categories are incompatible with schema

Se esegui il comando di copia da Google Cloud Shell, potresti ricevere un errore simile al seguente:

Latest categories are incompatible with schema at TIMESTAMP

Esistono diverse cause possibili per questo errore:

  • Lo schema della tabella di destinazione è diverso dallo schema della tabella originale (sono consentite colonne aggiuntive a condizione che non siano collegati tag di policy a livello di colonna ).
  • I tag di policy a livello di colonna della tabella di destinazione sono configurati in modo diverso rispetto alla tabella di origine.

Per risolvere questo errore:

  1. Assicurati che lo schema della tabella di destinazione sia identico e che nessuna delle colonne della tabella originale manchi nella tabella di destinazione.
  2. Rimuovi dalla tabella di destinazione tutti i tag di policy a livello di colonna che non sono presenti nello schema della tabella originale.

Errore: BigQuery error in cp operation: Invalid time travel timestamp

Se esegui il comando bq copy da Google Cloud Shell, potresti ricevere un errore simile al seguente:

BigQuery error in cp operation: Invalid time travel timestamp 1744343690000 for
table PROJECT_ID:DATASET_ID.TABLE_ID@1744343690000.
Cannot read before 1744843691075

Questo errore indica che stai tentando di recuperare i dati dallo stato della tabella prima della finestra di spostamento cronologico o prima della creazione della tabella. Questa operazione non è supportata. Il messaggio di errore contiene il timestamp più recente che può essere utilizzato per leggere i dati della tabella. Utilizza il timestamp nell'errore nel comando bq copy.

Questo errore può verificarsi anche quando fornisci un valore di timestamp negativo, ad esempio TABLE@-1744963620000. Utilizza invece un offset temporale che può essere utilizzato con il segno -.

BigQuery error in cp operation: Invalid time travel timestamp 584878816 for
table PROJECT_ID:DATASET_ID.TABLE_ID@584878816.
Cannot read before 1744843691075

Questo messaggio di errore indica che il comando bq cp contiene un valore di timestamp negativo come offset e che hai tentato di leggere la tabella in CURRENT_TIMESTAMP - PROVIDED TIMESTAMP. Questo valore è in genere un timestamp nel 1970. Per risolvere questo problema, verifica i valori di offset o timestamp quando imposti il valore del decoratore della tabella e utilizza il segno - in modo appropriato.

Viste materializzate

Non puoi ripristinare direttamente una vista materializzata eliminata. Se elimini una vista materializzata, devi ricrearla.

Se elimini una tabella che è una tabella di base per una vista materializzata, non è più possibile eseguire query o aggiornare la vista materializzata. Se ripristini la tabella di base seguendo i passaggi descritti in Ripristinare una tabella, devi anche ricreare tutte le viste materializzate che utilizzano quella tabella.

Tabelle esterne

Non puoi ripristinare direttamente una tabella esterna eliminata. Se elimini una tabella esterna, devi ricrearla. La procedura di ricreazione richiede di conoscere la definizione della tabella originale, in particolare quanto segue:

  • Lo schema della tabella
  • Gli URI di origine che rimandano ai dati esterni
  • Il formato dei dati esterni

Puoi ottenere queste informazioni da Cloud Logging cercando la voce di log di creazione della tabella. Puoi anche provare a ottenere gli URI eseguendo una query sulla INFORMATION_SCHEMA.TABLE_OPTIONS visualizzazione se la tabella è stata appena eliminata.

L'eliminazione della tabella esterna non comporta l'eliminazione dei dati sottostanti.

Passaggi successivi