Restaure tabelas eliminadas

Este documento descreve como restaurar (ou anular a eliminação) de uma tabela eliminada no BigQuery. Pode restaurar uma tabela eliminada no período de viagem no tempo especificado para o conjunto de dados, incluindo eliminações explícitas e eliminações implícitas devido à expiração da tabela. Também pode configurar o período de viagem no tempo.

Para obter informações sobre como restaurar um conjunto de dados ou uma imagem instantânea eliminada na totalidade, consulte os seguintes recursos:

O período de viagem no tempo pode ter uma duração entre dois e sete dias. Após o período de viagem no tempo, o BigQuery oferece um período de segurança em que os dados eliminados são automaticamente retidos durante mais sete dias. Após o período de segurança, não é possível restaurar uma tabela através de nenhum método, incluindo a abertura de um pedido de apoio técnico.

Antes de começar

Certifique-se de que tem as autorizações da gestão de identidade e de acesso (IAM) necessárias para restaurar uma tabela eliminada.

Funções necessárias

Para receber as autorizações de que precisa para restaurar uma tabela eliminada, peça ao seu administrador para lhe conceder a função de IAM Utilizador do BigQuery (roles/bigquery.user) no projeto. Para mais informações sobre a atribuição de funções, consulte o artigo Faça a gestão do acesso a projetos, pastas e organizações.

Também pode conseguir as autorizações necessárias através de funções personalizadas ou outras funções predefinidas.

Restaure uma tabela

Pode restaurar uma tabela a partir de dados do histórico copiando os dados do histórico para uma nova tabela. A cópia de dados do histórico funciona mesmo que a tabela tenha sido eliminada ou tenha expirado, desde que a restaure dentro do período da janela de viagem no tempo.

Quando restaura uma tabela a partir de dados do histórico, as etiquetas da tabela de origem não são copiadas para a tabela de destino. As informações de particionamento de tabelas também não são copiadas para a tabela de destino. Para recriar o esquema de partição da tabela original, pode ver o pedido de criação da tabela inicial no Cloud Logging e usar essas informações para particionar a tabela restaurada.

Pode restaurar uma tabela que foi eliminada, mas que ainda está dentro do período de viagem no tempo, copiando a tabela para uma nova tabela através do decorador de tempo @<time>. Não pode consultar uma tabela eliminada, mesmo que use um decorador de tempo. Primeiro, tem de restaurá-lo.

Use a seguinte sintaxe com o decorador de tempo @<time>:

  • tableid@TIME, onde TIME é o número de milissegundos desde a época Unix.
  • tableid@-TIME_OFFSET onde TIME_OFFSET é o desvio relativo do tempo atual, em milissegundos.
  • tableid@0: especifica os dados históricos mais antigos disponíveis.

Para restaurar uma tabela, selecione uma das seguintes opções:

Consola

Não pode anular a eliminação de uma tabela através da Google Cloud consola.

bq

  1. In the Google Cloud console, activate Cloud Shell.

    Activate Cloud Shell

    At the bottom of the Google Cloud console, a Cloud Shell session starts and displays a command-line prompt. Cloud Shell is a shell environment with the Google Cloud CLI already installed and with values already set for your current project. It can take a few seconds for the session to initialize.

  2. Para restaurar uma tabela, determine primeiro uma indicação de tempo UNIX de quando a tabela existia (em milissegundos). Pode usar o comando date do Linux para gerar a indicação de tempo de época Unix a partir de um valor de indicação de tempo normal:

    date -d '2023-08-04 16:00:34.456789Z' +%s000
    
  3. Em seguida, use o comando bq copy com o decorador de viagem no tempo @<time> para realizar a operação de cópia da tabela.

    Por exemplo, introduza o seguinte comando para copiar a tabela mydataset.mytable no momento 1418864998000 para uma nova tabela mydataset.newtable.

    bq cp mydataset.mytable@1418864998000 mydataset.newtable
    

    (Opcional) Forneça a flag --location e defina o valor para a sua localização.

    Também pode especificar um desvio relativo. O exemplo seguinte copia a versão de uma tabela de há uma hora:

    bq cp mydataset.mytable@-3600000 mydataset.newtable
    
  4. Ir

    Antes de experimentar este exemplo, siga as Goinstruções de configuração no início rápido do BigQuery com bibliotecas cliente. Para mais informações, consulte a API Go BigQuery documentação de referência.

    Para se autenticar no BigQuery, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para bibliotecas de cliente.

    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

    Antes de experimentar este exemplo, siga as Javainstruções de configuração no início rápido do BigQuery com bibliotecas cliente. Para mais informações, consulte a API Java BigQuery documentação de referência.

    Para se autenticar no BigQuery, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para bibliotecas de cliente.

    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

    Antes de experimentar este exemplo, siga as Node.jsinstruções de configuração no início rápido do BigQuery com bibliotecas cliente. Para mais informações, consulte a API Node.js BigQuery documentação de referência.

    Para se autenticar no BigQuery, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para bibliotecas de cliente.

    // 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

    Antes de experimentar este exemplo, siga as Pythoninstruções de configuração no início rápido do BigQuery com bibliotecas cliente. Para mais informações, consulte a API Python BigQuery documentação de referência.

    Para se autenticar no BigQuery, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para bibliotecas de cliente.

    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 prevê que pode querer restaurar uma tabela mais tarde do que o permitido pelo período de viagem no tempo, crie uma imagem instantânea da tabela. Para mais informações, consulte o artigo Introdução às capturas instantâneas de tabelas.

Não pode restaurar uma vista lógica diretamente. Para mais informações, consulte o artigo Restaure uma vista.

Resolva problemas de recuperação de tabelas

Consultar a tabela eliminada com uma data/hora no passado

Não pode restaurar dados de tabelas consultando uma tabela eliminada no passado através de um decorador de data/hora ou usando FOR SYSTEM_TIME AS OF para guardar o resultado numa tabela de destino. A utilização de qualquer um destes métodos gera o seguinte erro:

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

Em alternativa, para copiar a tabela, siga os passos em Restaurar uma tabela.

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

Quando tenta executar o comando de cópia a partir do Google Cloud Shell, pode encontrar um erro semelhante ao seguinte:

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

A utilização do Cloud Shell a partir da Google Cloud consola com o VPC SC não é suportada, porque é tratada como um pedido fora dos perímetros de serviço e o acesso aos dados protegidos pelos VPC Service Controls é negado. Para contornar este problema, inicie e ligue-se ao Cloud Shell localmente com a CLI Google Cloud.

Erro: Latest categories are incompatible with schema

Se executar o comando de cópia a partir do Google Cloud Shell, pode receber um erro semelhante ao seguinte:

Latest categories are incompatible with schema at TIMESTAMP

Há várias causas possíveis para este erro:

Para resolver este erro:

  1. Certifique-se de que o esquema da tabela de destino é idêntico e de que nenhuma das colunas da tabela original está em falta na tabela de destino.
  2. Remova todas as etiquetas de políticas ao nível da coluna da tabela de destino que não estejam no esquema da tabela original.

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

Se executar o comando bq copy a partir do Google Cloud Shell, pode receber um erro semelhante ao seguinte:

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

Este erro indica que está a tentar recuperar dados do estado da tabela antes do período de viagem no tempo ou antes da criação da tabela. Isto não é suportado. A mensagem de erro contém a data/hora mais recente que pode ser usada para ler os dados da tabela. Use a indicação de tempo no erro no comando bq copy.

Este erro também pode ocorrer quando fornece um valor de data/hora negativo, por exemplo, TABLE@-1744963620000. Em alternativa, use um desvio de tempo que possa ser usado com o sinal -.

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

Esta mensagem de erro indica que o comando bq cp contém um valor de data/hora negativo como um desvio e que tentou ler a tabela em CURRENT_TIMESTAMP - PROVIDED TIMESTAMP. Normalmente, este valor é uma data/hora em 1970. Para contornar este problema, valide os valores de deslocamento ou data/hora quando definir o valor do decorador de tabela e use o sinal - adequadamente.

O que se segue?