Restaurar tabelas excluídas

Neste documento, descrevemos como restaurar (ou cancelar a exclusão) de uma tabela excluída no BigQuery. É possível restaurar uma tabela excluída dentro do período de tempo especificado para o conjunto de dados, incluindo exclusões explícitas e implícitas devido à expiração da tabela. Você também pode configurar a janela de viagem no tempo.

Para informações sobre como restaurar um conjunto de dados ou snapshot excluído por completo, consulte os seguintes recursos:

O período de viagem pode ser de dois a sete dias. Depois que a janela de viagem no tempo expira, o BigQuery oferece um período de segurança contra falhas em que os dados excluídos são retidos automaticamente por mais sete dias. Depois que o período de segurança expira, não é possível restaurar uma tabela usando qualquer método, incluindo a abertura de um tíquete de suporte.

Antes de começar

Verifique se você tem as permissões necessárias do Identity and Access Management (IAM) para restaurar uma tabela excluída.

Funções exigidas

Para receber as permissões necessárias para restaurar uma tabela excluída, peça ao administrador para conceder a você o papel do IAM de Usuário do BigQuery (roles/bigquery.user) no projeto. Para mais informações sobre a concessão de papéis, consulte Gerenciar o acesso a projetos, pastas e organizações.

Também é possível conseguir as permissões necessárias usando papéis personalizados ou outros papéis predefinidos.

Restaurar uma tabela

Para restaurar uma tabela de dados históricos, copie-os para uma nova tabela. A cópia de dados históricos funciona mesmo que a tabela tenha sido excluída ou tenha expirado, desde que você restaure a tabela dentro do período da janela de viagem no tempo.

Ao restaurar uma tabela de dados históricos, as tags da tabela de origem não são copiadas para a tabela de destino. As informações de particionamento da tabela também não são copiadas para a tabela de destino. Para recriar o esquema de particionamento da tabela original, consulte a solicitação inicial de criação de tabela no Cloud Logging e use essas informações para particionar a tabela restaurada.

É possível restaurar uma tabela que foi excluída, mas ainda está dentro do período de viagem copiando-a para uma nova tabela usando o decorador de tempo @<time>. Não é possível consultar uma tabela excluída, mesmo que você use um decorador de tempo. Primeiro, restaure o dispositivo.

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

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

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

Console

Não é possível cancelar a exclusão de uma tabela usando o console do Google Cloud .

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, primeiro determine um carimbo de data/hora UNIX de quando ela existia (em milissegundos). É possível usar o comando date do Linux para gerar o carimbo de data/hora Unix a partir de um valor de carimbo de data/hora 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 executar a operação de cópia da tabela.

    Por exemplo, digite 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 sinalização --location e defina o valor do local.

    Também é possível especificar um deslocamento relativo. O exemplo a seguir copia a versão de uma tabela de uma hora atrás:

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

    Antes de testar esta amostra, siga as instruções de configuração do Go no Guia de início rápido do BigQuery: como usar bibliotecas de cliente. Para mais informações, consulte a documentação de referência da API BigQuery em Go.

    Para autenticar no BigQuery, configure o Application Default Credentials. Para mais informações, acesse Configurar 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 testar esta amostra, siga as instruções de configuração do Java no Guia de início rápido do BigQuery: como usar bibliotecas de cliente. Para mais informações, consulte a documentação de referência da API BigQuery em Java.

    Para autenticar no BigQuery, configure o Application Default Credentials. Para mais informações, acesse Configurar 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 testar esta amostra, siga as instruções de configuração do Node.js no Guia de início rápido do BigQuery: como usar bibliotecas de cliente. Para mais informações, consulte a documentação de referência da API BigQuery em Node.js.

    Para autenticar no BigQuery, configure o Application Default Credentials. Para mais informações, acesse Configurar 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 testar esta amostra, siga as instruções de configuração do Python no Guia de início rápido do BigQuery: como usar bibliotecas de cliente. Para mais informações, consulte a documentação de referência da API BigQuery em Python.

    Para autenticar no BigQuery, configure o Application Default Credentials. Para mais informações, acesse Configurar 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 você antecipar que talvez queira restaurar uma tabela mais tarde diferente da permitida pelo período de viagem, crie um snapshot da tabela. Para mais informações, consulte Introdução aos snapshots da tabela.

Não é possível restaurar uma visualização lógica diretamente. Para mais informações, consulte Restaurar uma visualização.

Resolver problemas de recuperação de tabela

Consultar a tabela excluída usando um carimbo de data/hora no passado

Não é possível restaurar dados de tabela consultando uma tabela excluída no passado usando um decorador de carimbo de data/hora ou usando FOR SYSTEM_TIME AS OF para salvar o resultado em uma tabela de destino. Usar qualquer um desses métodos gera o seguinte erro:

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

Em vez disso, siga as etapas em Restaurar uma tabela para copiar a tabela.

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

Ao tentar executar o comando de cópia do Google Cloud Shell, você pode encontrar um erro como este:

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

O uso do Cloud Shell no console Google Cloud com o VPC SC não é compatível, porque ele é tratado como uma solicitação fora dos perímetros de serviço, e o acesso aos dados protegidos pelo VPC Service Controls é negado. Para contornar esse problema, inicie e conecte-se ao Cloud Shell localmente com a Google Cloud CLI.

Erro: Latest categories are incompatible with schema

Se você executar o comando de cópia no Google Cloud Shell, poderá receber um erro como este:

Latest categories are incompatible with schema at TIMESTAMP

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

Para resolver esse erro:

  1. Verifique se o esquema da tabela de destino é idêntico e se nenhuma das colunas da tabela original está faltando na tabela de destino.
  2. Remova da tabela de destino todas as tags de política no nível da coluna que não estão no esquema da tabela original.

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

Se você executar o comando bq copy no Google Cloud Shell, poderá receber um erro como este:

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

Esse erro indica que você está tentando recuperar dados do estado da tabela antes da janela de viagem no tempo ou antes da criação da tabela. Isso não é permitido. A mensagem de erro contém o carimbo de data/hora mais recente que pode ser usado para ler os dados da tabela. Use o carimbo de data/hora no erro do comando bq copy.

Esse erro também pode ocorrer quando você fornece um valor de carimbo de data/hora negativo, por exemplo, TABLE@-1744963620000. Em vez disso, use um ajuste 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

Essa mensagem de erro indica que o comando bq cp contém um valor de carimbo de data/hora negativo como um deslocamento e que você tentou ler a tabela em CURRENT_TIMESTAMP - PROVIDED TIMESTAMP. Normalmente, esse valor é um carimbo de data/hora de 1970. Para resolver esse problema, verifique os valores de deslocamento ou carimbo de data/hora ao definir o valor do decorador de tabela e use o sinal - corretamente.

A seguir