Restaurar tablas eliminadas

En este documento se describe cómo restaurar (o recuperar) una tabla eliminada en BigQuery. Puedes restaurar una tabla eliminada en el periodo de viaje en el tiempo especificado para el conjunto de datos, incluidas las eliminaciones explícitas y las implícitas debido al vencimiento de la tabla. También puedes configurar la ventana de viaje en el tiempo.

Para obtener información sobre cómo restaurar un conjunto de datos o una instantánea eliminados, consulta los siguientes recursos:

La ventana de viaje en el tiempo puede tener una duración de entre dos y siete días. Una vez que ha pasado el periodo de recuperación, BigQuery ofrece un periodo de seguridad en el que los datos eliminados se conservan automáticamente durante siete días más. Una vez que haya pasado el periodo de seguridad, no se podrá restaurar una tabla con ningún método, ni siquiera abriendo una incidencia de asistencia.

Antes de empezar

Asegúrate de que tienes los permisos de gestión de identidades y accesos (IAM) necesarios para restaurar una tabla eliminada.

Roles obligatorios

Para obtener los permisos que necesitas para restaurar una tabla eliminada, pide a tu administrador que te asigne el rol de gestión de identidades y accesos Usuario de BigQuery (roles/bigquery.user) en el proyecto. Para obtener más información sobre cómo conceder roles, consulta el artículo Gestionar acceso a proyectos, carpetas y organizaciones.

También puedes conseguir los permisos necesarios a través de roles personalizados u otros roles predefinidos.

Restaurar una tabla

Puedes restaurar una tabla a partir de datos históricos copiando los datos históricos en una tabla nueva. La copia de datos históricos funciona aunque la tabla se haya eliminado o haya caducado, siempre que la restaure durante el periodo de la ventana de viaje en el tiempo.

Cuando restauras una tabla a partir de datos históricos, las etiquetas de la tabla de origen no se copian en la tabla de destino. La información de partición de la tabla tampoco se copia en la tabla de destino. Para recrear el esquema de partición de la tabla original, puedes ver la solicitud de creación de la tabla inicial en Cloud Logging y usar esa información para crear particiones en la tabla restaurada.

Puedes restaurar una tabla que se haya eliminado, pero que aún esté dentro del periodo de la función de viaje en el tiempo, copiándola en una tabla nueva con el decorador de tiempo @<time>. No puedes consultar una tabla eliminada, aunque uses un decorador de tiempo. Primero debes restaurarlo.

Usa la siguiente sintaxis con el decorador de tiempo @<time>:

  • tableid@TIME, donde TIME es el número de milisegundos transcurridos desde el inicio del registro de tiempo Unix.
  • tableid@-TIME_OFFSET, donde TIME_OFFSET es el desplazamiento relativo desde la hora actual, en milisegundos.
  • tableid@0: especifica los datos históricos más antiguos disponibles.

Para restaurar una tabla, selecciona una de las siguientes opciones:

Consola

No puedes restaurar una tabla eliminada con la 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 una tabla, primero debes determinar la marca de tiempo UNIX de cuándo existía la tabla (en milisegundos). Puedes usar el comando date de Linux para generar la marca de tiempo de Unix a partir de un valor de marca de tiempo normal:

    date -d '2023-08-04 16:00:34.456789Z' +%s000
    
  3. A continuación, usa el comando bq copy con el decorador de viaje en el tiempo @<time> para copiar la tabla.

    Por ejemplo, introduce el siguiente comando para copiar la tabla mydataset.mytable en el momento 1418864998000 en una tabla nueva mydataset.newtable.

    bq cp mydataset.mytable@1418864998000 mydataset.newtable
    

    (Opcional) Proporcione la marca --location y asigne el valor a su ubicación.

    También puedes especificar una variación relativa. En el siguiente ejemplo se copia la versión de una tabla de hace una hora:

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

    Antes de probar este ejemplo, sigue las Goinstrucciones de configuración de la guía de inicio rápido de BigQuery con bibliotecas de cliente. Para obtener más información, consulta la documentación de referencia de la API Go de BigQuery.

    Para autenticarte en BigQuery, configura las credenciales predeterminadas de la aplicación. Para obtener más información, consulta el artículo Configurar la autenticación 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 probar este ejemplo, sigue las Javainstrucciones de configuración de la guía de inicio rápido de BigQuery con bibliotecas de cliente. Para obtener más información, consulta la documentación de referencia de la API Java de BigQuery.

    Para autenticarte en BigQuery, configura las credenciales predeterminadas de la aplicación. Para obtener más información, consulta el artículo Configurar la autenticación 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 probar este ejemplo, sigue las Node.jsinstrucciones de configuración de la guía de inicio rápido de BigQuery con bibliotecas de cliente. Para obtener más información, consulta la documentación de referencia de la API Node.js de BigQuery.

    Para autenticarte en BigQuery, configura las credenciales predeterminadas de la aplicación. Para obtener más información, consulta el artículo Configurar la autenticación 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 probar este ejemplo, sigue las Pythoninstrucciones de configuración de la guía de inicio rápido de BigQuery con bibliotecas de cliente. Para obtener más información, consulta la documentación de referencia de la API Python de BigQuery.

    Para autenticarte en BigQuery, configura las credenciales predeterminadas de la aplicación. Para obtener más información, consulta el artículo Configurar la autenticación 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)
    )

Si prevé que puede que quiera restaurar una tabla más adelante de lo que permite el periodo de viaje en el tiempo, cree una instantánea de la tabla. Para obtener más información, consulta el artículo Introducción a las capturas de tablas.

No puedes restaurar una vista lógica directamente. Para obtener más información, consulta Restaurar una vista.

Solucionar problemas de recuperación de tablas

Consultar la tabla eliminada con una marca de tiempo anterior

No puedes restaurar los datos de una tabla consultando una tabla eliminada en el pasado con un decorador de marca de tiempo o usando FOR SYSTEM_TIME AS OF para guardar el resultado en una tabla de destino. Si utilizas cualquiera de estos métodos, se generará el siguiente error:

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

En su lugar, para copiar la tabla, siga los pasos que se indican en Restaurar una tabla.

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

Cuando intentes ejecutar el comando de copia desde Google Cloud Shell, es posible que se produzca un error como el siguiente:

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

No se puede usar Cloud Shell desde la Google Cloud consola con Controles de Servicio de VPC, ya que se trata como una solicitud fuera de los perímetros de servicio y se deniega el acceso a los datos que protege Controles de Servicio de VPC. Para solucionar este problema, inicia y conéctate a Cloud Shell de forma local con Google Cloud CLI.

Error: Latest categories are incompatible with schema

Si ejecutas el comando de copia desde Google Cloud Shell, es posible que recibas un error como el siguiente:

Latest categories are incompatible with schema at TIMESTAMP

Este error puede deberse a varios motivos:

Para resolver este error:

  1. Asegúrate de que el esquema de la tabla de destino sea idéntico y de que no falte ninguna columna de la tabla original en la tabla de destino.
  2. Quita las etiquetas de política a nivel de columna de la tabla de destino que no estén en el esquema de la tabla original.

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

Si ejecutas el comando bq copy desde Google Cloud Shell, puede que recibas un error como el siguiente:

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

Este error indica que estás intentando recuperar datos del estado de la tabla antes del periodo de retroceso en el tiempo o antes de que se creara la tabla. Esta opción no está disponible. El mensaje de error contiene la marca de tiempo más reciente que se puede usar para leer los datos de la tabla. Usa la marca de tiempo del error en el comando bq copy.

Este error también puede producirse si proporciona un valor de marca de tiempo negativo, como TABLE@-1744963620000. En su lugar, use un desfase horario que se pueda usar con el signo -.

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

Este mensaje de error indica que el comando bq cp contiene un valor de marca de tiempo negativo como desplazamiento y que has intentado leer la tabla en CURRENT_TIMESTAMP - PROVIDED TIMESTAMP. Normalmente, este valor es una marca de tiempo de 1970. Para solucionar este problema, verifique los valores de desplazamiento o de marca de tiempo al definir el valor del decorador de tabla y use el signo - correctamente.

Siguientes pasos