使用客户端库备份和恢复数据库

使用集合让一切井井有条 根据您的偏好保存内容并对其进行分类。

本页面介绍如何通过客户端库进行 Cloud Spanner 备份和恢复

如需了解如何安装和设置客户端库,请参阅 Cloud Spanner 客户端库

创建备份

以下代码示例在特定的 version_time 中创建备份,并等待备份完成。完成后,它会验证备份是否准备就绪,并检索有关该备份的一些信息,例如其名称、大小和创建时间。

C#

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库


using Google.Cloud.Spanner.Admin.Database.V1;
using Google.Cloud.Spanner.Common.V1;
using Google.LongRunning;
using Google.Protobuf.WellKnownTypes;
using System;

public class CreateBackupSample
{
    public Backup CreateBackup(string projectId, string instanceId, string databaseId, string backupId, DateTime versionTime)
    {
        // Create the DatabaseAdminClient instance.
        DatabaseAdminClient databaseAdminClient = DatabaseAdminClient.Create();

        // Initialize request parameters.
        Backup backup = new Backup
        {
            DatabaseAsDatabaseName = DatabaseName.FromProjectInstanceDatabase(projectId, instanceId, databaseId),
            ExpireTime = DateTime.UtcNow.AddDays(14).ToTimestamp(),
            VersionTime = versionTime.ToTimestamp(),
        };
        InstanceName instanceName = InstanceName.FromProjectInstance(projectId, instanceId);

        // Make the CreateBackup request.
        Operation<Backup, CreateBackupMetadata> response = databaseAdminClient.CreateBackup(instanceName, backup, backupId);

        Console.WriteLine("Waiting for the operation to finish.");

        // Poll until the returned long-running operation is complete.
        Operation<Backup, CreateBackupMetadata> completedResponse = response.PollUntilCompleted();

        if (completedResponse.IsFaulted)
        {
            Console.WriteLine($"Error while creating backup: {completedResponse.Exception}");
            throw completedResponse.Exception;
        }

        Console.WriteLine($"Backup created successfully.");

        // GetBackup to get more information about the created backup.
        BackupName backupName = BackupName.FromProjectInstanceBackup(projectId, instanceId, backupId);
        backup = databaseAdminClient.GetBackup(backupName);
        Console.WriteLine($"Backup {backup.Name} of size {backup.SizeBytes} bytes " +
                      $"was created at {backup.CreateTime} from {backup.Database} " +
                      $"and is in state {backup.State} " +
                      $"and has version time {backup.VersionTime.ToDateTime()}");
        return backup;
    }
}

C++

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库

void CreateBackup(google::cloud::spanner_admin::DatabaseAdminClient client,
                  std::string const& project_id, std::string const& instance_id,
                  std::string const& database_id, std::string const& backup_id,
                  google::cloud::spanner::Timestamp expire_time,
                  google::cloud::spanner::Timestamp version_time) {
  google::cloud::spanner::Database database(project_id, instance_id,
                                            database_id);
  google::spanner::admin::database::v1::CreateBackupRequest request;
  request.set_parent(database.instance().FullName());
  request.set_backup_id(backup_id);
  request.mutable_backup()->set_database(database.FullName());
  *request.mutable_backup()->mutable_expire_time() =
      expire_time.get<google::protobuf::Timestamp>().value();
  *request.mutable_backup()->mutable_version_time() =
      version_time.get<google::protobuf::Timestamp>().value();
  auto backup = client.CreateBackup(request).get();
  if (!backup) throw std::runtime_error(backup.status().message());
  std::cout
      << "Backup " << backup->name() << " of " << backup->database()
      << " of size " << backup->size_bytes() << " bytes"
      << " was created at "
      << google::cloud::spanner::MakeTimestamp(backup->create_time()).value()
      << ".\n";
}

Go

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库


import (
	"context"
	"fmt"
	"io"
	"regexp"
	"time"

	database "cloud.google.com/go/spanner/admin/database/apiv1"
	pbt "github.com/golang/protobuf/ptypes/timestamp"
	adminpb "google.golang.org/genproto/googleapis/spanner/admin/database/v1"
)

func createBackup(ctx context.Context, w io.Writer, db, backupID string, versionTime time.Time) error {
	// versionTime := time.Now().AddDate(0, 0, -1) // one day ago
	matches := regexp.MustCompile("^(.+)/databases/(.+)$").FindStringSubmatch(db)
	if matches == nil || len(matches) != 3 {
		return fmt.Errorf("createBackup: invalid database id %q", db)
	}

	adminClient, err := database.NewDatabaseAdminClient(ctx)
	if err != nil {
		return fmt.Errorf("createBackup.NewDatabaseAdminClient: %v", err)
	}
	defer adminClient.Close()

	expireTime := time.Now().AddDate(0, 0, 14)
	// Create a backup.
	req := adminpb.CreateBackupRequest{
		Parent:   matches[1],
		BackupId: backupID,
		Backup: &adminpb.Backup{
			Database:    db,
			ExpireTime:  &pbt.Timestamp{Seconds: expireTime.Unix(), Nanos: int32(expireTime.Nanosecond())},
			VersionTime: &pbt.Timestamp{Seconds: versionTime.Unix(), Nanos: int32(versionTime.Nanosecond())},
		},
	}
	op, err := adminClient.CreateBackup(ctx, &req)
	if err != nil {
		return fmt.Errorf("createBackup.CreateBackup: %v", err)
	}
	// Wait for backup operation to complete.
	backup, err := op.Wait(ctx)
	if err != nil {
		return fmt.Errorf("createBackup.Wait: %v", err)
	}

	// Get the name, create time, version time and backup size.
	backupCreateTime := time.Unix(backup.CreateTime.Seconds, int64(backup.CreateTime.Nanos))
	backupVersionTime := time.Unix(backup.VersionTime.Seconds, int64(backup.VersionTime.Nanos))
	fmt.Fprintf(w,
		"Backup %s of size %d bytes was created at %s with version time %s\n",
		backup.Name,
		backup.SizeBytes,
		backupCreateTime.Format(time.RFC3339),
		backupVersionTime.Format(time.RFC3339))
	return nil
}

Java

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库

static void createBackup(DatabaseAdminClient dbAdminClient, DatabaseId databaseId,
    BackupId backupId, Timestamp versionTime) {
  // Set expire time to 14 days from now.
  Timestamp expireTime = Timestamp.ofTimeMicroseconds(TimeUnit.MICROSECONDS.convert(
      System.currentTimeMillis() + TimeUnit.DAYS.toMillis(14), TimeUnit.MILLISECONDS));
  Backup backup =
      dbAdminClient
          .newBackupBuilder(backupId)
          .setDatabase(databaseId)
          .setExpireTime(expireTime)
          .setVersionTime(versionTime)
          .build();
  // Initiate the request which returns an OperationFuture.
  System.out.println("Creating backup [" + backup.getId() + "]...");
  OperationFuture<Backup, CreateBackupMetadata> op = backup.create();
  try {
    // Wait for the backup operation to complete.
    backup = op.get();
    System.out.println("Created backup [" + backup.getId() + "]");
  } catch (ExecutionException e) {
    throw (SpannerException) e.getCause();
  } catch (InterruptedException e) {
    throw SpannerExceptionFactory.propagateInterrupt(e);
  }

  // Reload the metadata of the backup from the server.
  backup = backup.reload();
  System.out.println(
      String.format(
          "Backup %s of size %d bytes was created at %s for version of database at %s",
          backup.getId().getName(),
          backup.getSize(),
          LocalDateTime.ofEpochSecond(
              backup.getProto().getCreateTime().getSeconds(),
              backup.getProto().getCreateTime().getNanos(),
              OffsetDateTime.now().getOffset()),
          LocalDateTime.ofEpochSecond(
              backup.getProto().getVersionTime().getSeconds(),
              backup.getProto().getVersionTime().getNanos(),
              OffsetDateTime.now().getOffset())
          ));
}

Node.js

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库

// Imports the Google Cloud client library and precise date library
const {Spanner} = require('@google-cloud/spanner');
const {PreciseDate} = require('@google-cloud/precise-date');

/**
 * TODO(developer): Uncomment the following lines before running the sample.
 */
// const projectId = 'my-project-id';
// const instanceId = 'my-instance';
// const databaseId = 'my-database';
// const backupId = 'my-backup';
// const versionTime = Date.now() - 1000 * 60 * 60 * 24; // One day ago

// Creates a client
const spanner = new Spanner({
  projectId: projectId,
});

// Gets a reference to a Cloud Spanner instance and database
const instance = spanner.instance(instanceId);
const database = instance.database(databaseId);

const backup = instance.backup(backupId);

// Creates a new backup of the database
try {
  console.log(`Creating backup of database ${database.formattedName_}.`);
  const databasePath = database.formattedName_;
  // Expire backup 14 days in the future
  const expireTime = Date.now() + 1000 * 60 * 60 * 24 * 14;
  // Create a backup of the state of the database at the current time.
  const [, operation] = await backup.create({
    databasePath: databasePath,
    expireTime: expireTime,
    versionTime: versionTime,
  });

  console.log(`Waiting for backup ${backup.formattedName_} to complete...`);
  await operation.promise();

  // Verify backup is ready
  const [backupInfo] = await backup.getMetadata();
  if (backupInfo.state === 'READY') {
    console.log(
      `Backup ${backupInfo.name} of size ` +
        `${backupInfo.sizeBytes} bytes was created at ` +
        `${new PreciseDate(backupInfo.createTime).toISOString()} ` +
        'for version of database at ' +
        `${new PreciseDate(backupInfo.versionTime).toISOString()}`
    );
  } else {
    console.error('ERROR: Backup is not ready.');
  }
} catch (err) {
  console.error('ERROR:', err);
} finally {
  // Close the database when finished.
  await database.close();
}

PHP

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库

use Google\Cloud\Spanner\Backup;
use Google\Cloud\Spanner\SpannerClient;

/**
 * Create a backup.
 * Example:
 * ```
 * create_backup($instanceId, $databaseId, $backupId, $versionTime);
 * ```
 *
 * @param string $instanceId The Spanner instance ID.
 * @param string $databaseId The Spanner database ID.
 * @param string $backupId The Spanner backup ID.
 * @param string $versionTime The version of the database to backup.
 */
function create_backup($instanceId, $databaseId, $backupId, $versionTime)
{
    $spanner = new SpannerClient();
    $instance = $spanner->instance($instanceId);
    $database = $instance->database($databaseId);

    $expireTime = new \DateTime('+14 days');
    $backup = $instance->backup($backupId);
    $operation = $backup->create($database->name(), $expireTime, [
        'versionTime' => new \DateTime($versionTime)
    ]);

    print('Waiting for operation to complete...' . PHP_EOL);
    $operation->pollUntilComplete();

    $backup->reload();
    $ready = ($backup->state() == Backup::STATE_READY);

    if ($ready) {
        print('Backup is ready!' . PHP_EOL);
        $info = $backup->info();
        printf(
            'Backup %s of size %d bytes was created at %s for version of database at %s' . PHP_EOL,
            basename($info['name']), $info['sizeBytes'], $info['createTime'], $info['versionTime']);
    } else {
        print('Backup is not ready!' . PHP_EOL);
    }
}

Python

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库

def create_backup(instance_id, database_id, backup_id, version_time):
    """Creates a backup for a database."""
    spanner_client = spanner.Client()
    instance = spanner_client.instance(instance_id)
    database = instance.database(database_id)

    # Create a backup
    expire_time = datetime.utcnow() + timedelta(days=14)
    backup = instance.backup(backup_id, database=database, expire_time=expire_time, version_time=version_time)
    operation = backup.create()

    # Wait for backup operation to complete.
    operation.result(2100)

    # Verify that the backup is ready.
    backup.reload()
    assert backup.is_ready() is True

    # Get the name, create time and backup size.
    backup.reload()
    print(
        "Backup {} of size {} bytes was created at {} for version of database at {}".format(
            backup.name, backup.size_bytes, backup.create_time, backup.version_time
        )
    )

Ruby

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库

# project_id  = "Your Google Cloud project ID"
# instance_id = "Your Spanner instance ID"
# database_id = "Your Spanner database ID"
# backup_id = "Your Spanner backup ID"
# version_time = Time.now - 60 * 60 * 24 # 1 day ago

require "google/cloud/spanner"
require "google/cloud/spanner/admin/database"

database_admin_client = Google::Cloud::Spanner::Admin::Database.database_admin

instance_path = database_admin_client.instance_path project: project_id, instance: instance_id
db_path = database_admin_client.database_path project: project_id,
                                              instance: instance_id,
                                              database: database_id
backup_path = database_admin_client.backup_path project: project_id,
                                                instance: instance_id,
                                                backup: backup_id
expire_time = Time.now + 14 * 24 * 3600 # 14 days from now

job = database_admin_client.create_backup parent: instance_path,
                                          backup_id: backup_id,
                                          backup: {
                                            database: db_path,
                                              expire_time: expire_time,
                                              version_time: version_time
                                          }

puts "Backup operation in progress"

job.wait_until_done!

backup = database_admin_client.get_backup name: backup_path
puts "Backup #{backup_id} of size #{backup.size_bytes} bytes was created at #{backup.create_time} for version of database at #{backup.version_time}"

列出备份操作

以下代码示例列出按给定数据库过滤的所有创建备份操作(使用 CreateBackupMetadata 的操作),并打印仍在进行中的操作。

如需了解过滤语法,请参阅 List BackupOperations 中的 filter 参数。

C#

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库


using Google.Cloud.Spanner.Admin.Database.V1;
using Google.Cloud.Spanner.Common.V1;
using Google.LongRunning;
using System;
using System.Collections.Generic;

public class ListBackupOperationsSample
{
    public IEnumerable<Operation> ListBackupOperations(string projectId, string instanceId, string databaseId)
    {
        // Create the DatabaseAdminClient instance.
        DatabaseAdminClient databaseAdminClient = DatabaseAdminClient.Create();

        var filter = $"(metadata.database:{databaseId}) AND (metadata.@type:type.googleapis.com/google.spanner.admin.database.v1.CreateBackupMetadata)";
        ListBackupOperationsRequest request = new ListBackupOperationsRequest
        {
            ParentAsInstanceName = InstanceName.FromProjectInstance(projectId, instanceId),
            Filter = filter
        };

        // List the create backup operations on the database.
        var backupOperations = databaseAdminClient.ListBackupOperations(request);

        foreach (var operation in backupOperations)
        {
            CreateBackupMetadata metadata = operation.Metadata.Unpack<CreateBackupMetadata>();
            Console.WriteLine($"Backup {metadata.Name} on " + $"database {metadata.Database} is " + $"{metadata.Progress.ProgressPercent}% complete");
        }

        return backupOperations;
    }
}

C++

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库

void ListBackupOperations(
    google::cloud::spanner_admin::DatabaseAdminClient client,
    std::string const& project_id, std::string const& instance_id,
    std::string const& database_id) {
  google::cloud::spanner::Instance in(project_id, instance_id);
  google::cloud::spanner::Database database(in, database_id);
  google::spanner::admin::database::v1::ListBackupOperationsRequest request;
  request.set_parent(in.FullName());
  request.set_filter(std::string("(metadata.@type=type.googleapis.com/") +
                     "google.spanner.admin.database.v1.CreateBackupMetadata)" +
                     " AND (metadata.database=" + database.FullName() + ")");
  for (auto const& operation : client.ListBackupOperations(request)) {
    if (!operation) throw std::runtime_error(operation.status().message());
    google::spanner::admin::database::v1::CreateBackupMetadata metadata;
    operation->metadata().UnpackTo(&metadata);
    std::cout << "Backup " << metadata.name() << " on database "
              << metadata.database()
              << " progress: " << metadata.progress().progress_percent()
              << "% complete.\n";
  }
}

Go

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库


import (
	"context"
	"fmt"
	"io"
	"regexp"

	database "cloud.google.com/go/spanner/admin/database/apiv1"
	"github.com/golang/protobuf/ptypes"
	"google.golang.org/api/iterator"
	adminpb "google.golang.org/genproto/googleapis/spanner/admin/database/v1"
)

func listBackupOperations(ctx context.Context, w io.Writer, db string) error {
	adminClient, err := database.NewDatabaseAdminClient(ctx)
	if err != nil {
		return err
	}
	defer adminClient.Close()

	matches := regexp.MustCompile("^(.*)/databases/(.*)$").FindStringSubmatch(db)
	if matches == nil || len(matches) != 3 {
		return fmt.Errorf("Invalid database id %s", db)
	}
	instanceName := matches[1]
	// List the CreateBackup operations.
	filter := fmt.Sprintf("(metadata.@type:type.googleapis.com/google.spanner.admin.database.v1.CreateBackupMetadata) AND (metadata.database:%s)", db)
	iter := adminClient.ListBackupOperations(ctx, &adminpb.ListBackupOperationsRequest{
		Parent: instanceName,
		Filter: filter,
	})
	for {
		resp, err := iter.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			return err
		}
		metadata := &adminpb.CreateBackupMetadata{}
		if err := ptypes.UnmarshalAny(resp.Metadata, metadata); err != nil {
			return err
		}
		fmt.Fprintf(w, "Backup %s on database %s is %d%% complete.\n",
			metadata.Name,
			metadata.Database,
			metadata.Progress.ProgressPercent,
		)
	}
	return nil
}

Java

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库

static void listBackupOperations(InstanceAdminClient instanceAdminClient, DatabaseId databaseId) {
  Instance instance = instanceAdminClient.getInstance(databaseId.getInstanceId().getInstance());
  // Get create backup operations for the sample database.
  Timestamp last24Hours = Timestamp.ofTimeSecondsAndNanos(TimeUnit.SECONDS.convert(
      TimeUnit.HOURS.convert(Timestamp.now().getSeconds(), TimeUnit.SECONDS) - 24,
      TimeUnit.HOURS), 0);
  String filter =
      String.format(
          "(metadata.database:%s) AND "
              + "(metadata.@type:type.googleapis.com/"
              + "google.spanner.admin.database.v1.CreateBackupMetadata) AND "
              + "(metadata.progress.start_time > \"%s\")",
          databaseId.getName(), last24Hours);
  Page<Operation> operations = instance.listBackupOperations(Options.filter(filter));
  for (Operation op : operations.iterateAll()) {
    try {
      CreateBackupMetadata metadata = op.getMetadata().unpack(CreateBackupMetadata.class);
      System.out.println(
          String.format(
              "Backup %s on database %s pending: %d%% complete",
              metadata.getName(),
              metadata.getDatabase(),
              metadata.getProgress().getProgressPercent()));
    } catch (InvalidProtocolBufferException e) {
      // The returned operation does not contain CreateBackupMetadata.
      System.err.println(e.getMessage());
    }
  }
}

Node.js

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库

// Imports the Google Cloud client library
const {Spanner, protos} = require('@google-cloud/spanner');

/**
 * TODO(developer): Uncomment the following lines before running the sample.
 */
// const projectId = 'my-project-id';
// const databaseId = 'my-database';
// const instanceId = 'my-instance';

// Creates a client
const spanner = new Spanner({
  projectId: projectId,
});

// Gets a reference to a Cloud Spanner instance
const instance = spanner.instance(instanceId);

// List backup operations
try {
  const [backupOperations] = await instance.getBackupOperations({
    filter:
      '(metadata.@type:type.googleapis.com/google.spanner.admin.database.v1.CreateBackupMetadata) ' +
      `AND (metadata.database:${databaseId})`,
  });
  console.log('Create Backup Operations:');
  backupOperations.forEach(backupOperation => {
    const metadata =
      protos.google.spanner.admin.database.v1.CreateBackupMetadata.decode(
        backupOperation.metadata.value
      );
    console.log(
      `Backup ${metadata.name} on database ${metadata.database} is ` +
        `${metadata.progress.progressPercent}% complete.`
    );
  });
} catch (err) {
  console.error('ERROR:', err);
}

PHP

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库

use Google\Cloud\Spanner\SpannerClient;

/**
 * List all create backup operations in an instance.
 * Example:
 * ```
 * list_backup_operations($instanceId, $databaseId);
 * ```
 *
 * @param string $instanceId The Spanner instance ID.
 * @param string $databaseId The Spanner database ID.
 */
function list_backup_operations($instanceId, $databaseId)
{
    $spanner = new SpannerClient();
    $instance = $spanner->instance($instanceId);

    // List the CreateBackup operations.
    $filter = "(metadata.database:$databaseId) AND " .
              '(metadata.@type:type.googleapis.com/' .
              'google.spanner.admin.database.v1.CreateBackupMetadata)';

    $operations = $instance->backupOperations(['filter' => $filter]);

    foreach ($operations as $operation) {
        if (!$operation->done()) {
            $meta = $operation->info()['metadata'];
            $backupName = basename($meta['name']);
            $dbName = basename($meta['database']);
            $progress = $meta['progress']['progressPercent'];
            printf('Backup %s on database %s is %d%% complete.' . PHP_EOL, $backupName, $dbName, $progress);
        }
    }
}

Python

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库

def list_backup_operations(instance_id, database_id):
    spanner_client = spanner.Client()
    instance = spanner_client.instance(instance_id)

    # List the CreateBackup operations.
    filter_ = (
        "(metadata.@type:type.googleapis.com/"
        "google.spanner.admin.database.v1.CreateBackupMetadata) "
        "AND (metadata.database:{})"
    ).format(database_id)
    operations = instance.list_backup_operations(filter_=filter_)
    for op in operations:
        metadata = op.metadata
        print(
            "Backup {} on database {}: {}% complete.".format(
                metadata.name, metadata.database, metadata.progress.progress_percent
            )
        )

Ruby

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库

# project_id  = "Your Google Cloud project ID"
# instance_id = "Your Spanner instance ID"
# database_id = "Your Spanner database ID"

require "google/cloud/spanner"
require "google/cloud/spanner/admin/database"

database_admin_client = Google::Cloud::Spanner::Admin::Database.database_admin
instance_path = database_admin_client.instance_path project: project_id, instance: instance_id

jobs = database_admin_client.list_backup_operations parent: instance_path,
                                                    filter: "metadata.@type:type.googleapis.com/google.spanner.admin.database.v1.CreateBackupMetadata"
jobs.each do |job|
  if job.error?
    puts job.error
  else
    puts "Backup #{job.results.name} on database #{database_id} is #{job.metadata.progress.progress_percent}% complete"
  end
end

从备份恢复数据库

以下代码示例从给定备份中恢复数据库,并等待恢复操作(使用 RestoreDatabaseMetadata 的操作)完成。恢复的数据库会在备份所在的实例中创建。完成后,示例将从数据库中检索并打印一些恢复信息。

C#

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库


using Google.Cloud.Spanner.Admin.Database.V1;
using Google.Cloud.Spanner.Common.V1;
using Google.LongRunning;
using System;

public class RestoreDatabaseSample
{
    public RestoreInfo RestoreDatabase(string projectId, string instanceId, string databaseId, string backupId)
    {
        // Create the DatabaseAdminClient instance.
        DatabaseAdminClient databaseAdminClient = DatabaseAdminClient.Create();

        InstanceName parentAsInstanceName = InstanceName.FromProjectInstance(projectId, instanceId);
        BackupName backupAsBackupName = BackupName.FromProjectInstanceBackup(projectId, instanceId, backupId);

        // Make the RestoreDatabase request.
        Operation<Database, RestoreDatabaseMetadata> response = databaseAdminClient.RestoreDatabase(parentAsInstanceName, databaseId, backupAsBackupName);

        Console.WriteLine("Waiting for the operation to finish");

        // Poll until the returned long-running operation is complete.
        var completedResponse = response.PollUntilCompleted();

        if (completedResponse.IsFaulted)
        {
            Console.WriteLine($"Database Restore Failed: {completedResponse.Exception}");
            throw completedResponse.Exception;
        }

        RestoreInfo restoreInfo = completedResponse.Result.RestoreInfo;
        Console.WriteLine(
            $"Database {restoreInfo.BackupInfo.SourceDatabase} was restored " +
            $"to {databaseId} from backup {restoreInfo.BackupInfo.Backup} " +
            $"with version time {restoreInfo.BackupInfo.VersionTime.ToDateTime()}");

        return restoreInfo;
    }
}

C++

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库

void RestoreDatabase(google::cloud::spanner_admin::DatabaseAdminClient client,
                     std::string const& project_id,
                     std::string const& instance_id,
                     std::string const& database_id,
                     std::string const& backup_id) {
  google::cloud::spanner::Database database(project_id, instance_id,
                                            database_id);
  google::cloud::spanner::Backup backup(database.instance(), backup_id);
  auto restored_db =
      client
          .RestoreDatabase(database.instance().FullName(),
                           database.database_id(), backup.FullName())
          .get();
  if (!restored_db) {
    throw std::runtime_error(restored_db.status().message());
  }
  std::cout << "Database";
  if (restored_db->restore_info().source_type() ==
      google::spanner::admin::database::v1::BACKUP) {
    auto const& backup_info = restored_db->restore_info().backup_info();
    std::cout << " " << backup_info.source_database() << " as of "
              << google::cloud::spanner::MakeTimestamp(
                     backup_info.version_time())
                     .value();
  }
  std::cout << " restored to " << restored_db->name();
  std::cout << " from backup " << backup.FullName();
  std::cout << ".\n";
}

Go

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库


import (
	"context"
	"fmt"
	"io"
	"regexp"

	database "cloud.google.com/go/spanner/admin/database/apiv1"
	adminpb "google.golang.org/genproto/googleapis/spanner/admin/database/v1"
)

func restoreBackup(ctx context.Context, w io.Writer, db, backupID string) error {
	adminClient, err := database.NewDatabaseAdminClient(ctx)
	if err != nil {
		return err
	}
	defer adminClient.Close()

	matches := regexp.MustCompile("^(.*)/databases/(.*)$").FindStringSubmatch(db)
	if matches == nil || len(matches) != 3 {
		return fmt.Errorf("Invalid database id %s", db)
	}
	instanceName := matches[1]
	databaseID := matches[2]
	backupName := instanceName + "/backups/" + backupID

	// Start restoring backup to a new database.
	restoreOp, err := adminClient.RestoreDatabase(ctx, &adminpb.RestoreDatabaseRequest{
		Parent:     instanceName,
		DatabaseId: databaseID,
		Source: &adminpb.RestoreDatabaseRequest_Backup{
			Backup: backupName,
		},
	})
	if err != nil {
		return err
	}
	// Wait for restore operation to complete.
	dbObj, err := restoreOp.Wait(ctx)
	if err != nil {
		return err
	}
	// Newly created database has restore information.
	backupInfo := dbObj.RestoreInfo.GetBackupInfo()
	if backupInfo != nil {
		fmt.Fprintf(w, "Source database %s restored from backup %s\n", backupInfo.SourceDatabase, backupInfo.Backup)
	}

	return nil
}

Java

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库

static void restoreBackup(
    DatabaseAdminClient dbAdminClient,
    BackupId backupId,
    DatabaseId sourceDatabaseId,
    DatabaseId restoreToDatabase) {
  Backup backup = dbAdminClient.newBackupBuilder(backupId).build();
  // Initiate the request which returns an OperationFuture.
  System.out.println(String.format(
      "Restoring backup [%s] to database [%s]...",
      backup.getId().toString(),
      restoreToDatabase.toString()));
  try {
    OperationFuture<Database, RestoreDatabaseMetadata> op = backup.restore(restoreToDatabase);
    // Wait until the database has been restored.
    Database db = op.get();
    // Refresh database metadata and get the restore info.
    RestoreInfo restore = db.reload().getRestoreInfo();
    Timestamp versionTime = Timestamp.fromProto(restore
        .getProto()
        .getBackupInfo()
        .getVersionTime());
    System.out.println(
        "Restored database ["
            + restore.getSourceDatabase().getName()
            + "] from ["
            + restore.getBackup().getName()
            + "] with version time [" + versionTime + "]");
  } catch (ExecutionException e) {
    throw SpannerExceptionFactory.newSpannerException(e.getCause());
  } catch (InterruptedException e) {
    throw SpannerExceptionFactory.propagateInterrupt(e);
  }
}

Node.js

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库

// Imports the Google Cloud client library and precise date library
const {Spanner} = require('@google-cloud/spanner');
const {PreciseDate} = require('@google-cloud/precise-date');

/**
 * TODO(developer): Uncomment the following lines before running the sample.
 */
// const projectId = 'my-project-id';
// const instanceId = 'my-instance';
// const databaseId = 'my-database';
// const backupId = 'my-backup';

// Creates a client
const spanner = new Spanner({
  projectId: projectId,
});

// Gets a reference to a Cloud Spanner instance and database
const instance = spanner.instance(instanceId);
const database = instance.database(databaseId);

// Restore the database
console.log(
  `Restoring database ${database.formattedName_} from backup ${backupId}.`
);
const [, restoreOperation] = await database.restore(
  `projects/${projectId}/instances/${instanceId}/backups/${backupId}`
);

// Wait for restore to complete
console.log('Waiting for database restore to complete...');
await restoreOperation.promise();

console.log('Database restored from backup.');
const restoreInfo = await database.getRestoreInfo();
console.log(
  `Database ${restoreInfo.backupInfo.sourceDatabase} was restored ` +
    `to ${databaseId} from backup ${restoreInfo.backupInfo.backup} ` +
    'with version time ' +
    `${new PreciseDate(restoreInfo.backupInfo.versionTime).toISOString()}.`
);

PHP

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库

use Google\Cloud\Spanner\SpannerClient;

/**
 * Restore a database from a backup.
 * Example:
 * ```
 * restore_backup($instanceId, $databaseId, $backupId);
 * ```
 * @param string $instanceId The Spanner instance ID.
 * @param string $databaseId The Spanner database ID.
 * @param string $backupId The Spanner backup ID.
 */
function restore_backup($instanceId, $databaseId, $backupId)
{
    $spanner = new SpannerClient();
    $instance = $spanner->instance($instanceId);
    $database = $instance->database($databaseId);
    $backup = $instance->backup($backupId);

    $operation = $database->restore($backup->name());
    // Wait for restore operation to complete.
    $operation->pollUntilComplete();

    // Newly created database has restore information.
    $database->reload();
    $restoreInfo = $database->info()['restoreInfo'];
    $sourceDatabase = $restoreInfo['backupInfo']['sourceDatabase'];
    $sourceBackup = $restoreInfo['backupInfo']['backup'];
    $versionTime = $restoreInfo['backupInfo']['versionTime'];

    printf(
        'Database %s restored from backup %s with version time %s' . PHP_EOL,
        $sourceDatabase, $sourceBackup, $versionTime);
}

Python

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库

def restore_database(instance_id, new_database_id, backup_id):
    """Restores a database from a backup."""
    spanner_client = spanner.Client()
    instance = spanner_client.instance(instance_id)
    # Create a backup on database_id.

    # Start restoring an existing backup to a new database.
    backup = instance.backup(backup_id)
    new_database = instance.database(new_database_id)
    operation = new_database.restore(backup)

    # Wait for restore operation to complete.
    operation.result(1600)

    # Newly created database has restore information.
    new_database.reload()
    restore_info = new_database.restore_info
    print(
        "Database {} restored to {} from backup {} with version time {}.".format(
            restore_info.backup_info.source_database,
            new_database_id,
            restore_info.backup_info.backup,
            restore_info.backup_info.version_time
        )
    )

Ruby

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库

# project_id  = "Your Google Cloud project ID"
# instance_id = "Your Spanner instance ID"
# database_id = "Your Spanner database ID of where to restore"
# backup_id = "Your Spanner backup ID"

require "google/cloud/spanner"
require "google/cloud/spanner/admin/database"

database_admin_client = Google::Cloud::Spanner::Admin::Database.database_admin

instance_path = database_admin_client.instance_path project: project_id, instance: instance_id

db_path = database_admin_client.database_path project: project_id,
                                              instance: instance_id,
                                              database: database_id

backup_path = database_admin_client.backup_path project: project_id,
                                                instance: instance_id,
                                                backup: backup_id

job = database_admin_client.restore_database parent: instance_path,
                                             database_id: database_id,
                                             backup: backup_path

puts "Waiting for restore backup operation to complete"

job.wait_until_done!

database = database_admin_client.get_database name: db_path
restore_info = database.restore_info
puts "Database #{restore_info.backup_info.source_database} was restored to #{database_id} from backup #{restore_info.backup_info.backup} with version time #{restore_info.backup_info.version_time}"

列出数据库操作

以下代码示例列出按给定数据库过滤的优化数据库操作(使用 OptimizeRestoredDatabaseMetadata 的操作)。

如需了解过滤语法,请参阅列出数据库操作中的 filter 参数。

C#

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库


using Google.Cloud.Spanner.Admin.Database.V1;
using Google.Cloud.Spanner.Common.V1;
using Google.LongRunning;
using System;
using System.Collections.Generic;

public class ListDatabaseOperationsSample
{
    public IEnumerable<Operation> ListDatabaseOperations(string projectId, string instanceId)
    {
        // Create the DatabaseAdminClient instance.
        DatabaseAdminClient databaseAdminClient = DatabaseAdminClient.Create();

        var filter = "(metadata.@type:type.googleapis.com/google.spanner.admin.database.v1.OptimizeRestoredDatabaseMetadata)";

        ListDatabaseOperationsRequest request = new ListDatabaseOperationsRequest
        {
            ParentAsInstanceName = InstanceName.FromProjectInstance(projectId, instanceId),
            Filter = filter
        };

        // List the optimize restored databases operations on the instance.
        var operations = databaseAdminClient.ListDatabaseOperations(request);

        foreach (var operation in operations)
        {
            OptimizeRestoredDatabaseMetadata metadata =
                operation.Metadata.Unpack<OptimizeRestoredDatabaseMetadata>();
            Console.WriteLine(
                $"Database {metadata.Name} restored from backup is {metadata.Progress.ProgressPercent}% optimized.");
        }

        return operations;
    }
}

C++

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库

void ListDatabaseOperations(
    google::cloud::spanner_admin::DatabaseAdminClient client,
    std::string const& project_id, std::string const& instance_id) {
  google::cloud::spanner::Instance in(project_id, instance_id);
  google::spanner::admin::database::v1::ListDatabaseOperationsRequest request;
  request.set_parent(in.FullName());
  request.set_filter(
      "(metadata.@type:type.googleapis.com/"
      "google.spanner.admin.database.v1.OptimizeRestoredDatabaseMetadata)");
  for (auto const& operation : client.ListDatabaseOperations(request)) {
    if (!operation) throw std::runtime_error(operation.status().message());
    google::spanner::admin::database::v1::OptimizeRestoredDatabaseMetadata
        metadata;
    operation->metadata().UnpackTo(&metadata);
    std::cout << "Database " << metadata.name() << " restored from backup is "
              << metadata.progress().progress_percent() << "% optimized.\n";
  }
}

Go

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库


import (
	"context"
	"fmt"
	"io"
	"regexp"

	database "cloud.google.com/go/spanner/admin/database/apiv1"
	"github.com/golang/protobuf/ptypes"
	"google.golang.org/api/iterator"
	adminpb "google.golang.org/genproto/googleapis/spanner/admin/database/v1"
)

func listDatabaseOperations(ctx context.Context, w io.Writer, db string) error {
	adminClient, err := database.NewDatabaseAdminClient(ctx)
	if err != nil {
		return err
	}
	defer adminClient.Close()

	matches := regexp.MustCompile("^(.*)/databases/(.*)$").FindStringSubmatch(db)
	if matches == nil || len(matches) != 3 {
		return fmt.Errorf("Invalid database id %s", db)
	}
	instanceName := matches[1]
	// List the databases that are being optimized after a restore operation.
	filter := "(metadata.@type:type.googleapis.com/google.spanner.admin.database.v1.OptimizeRestoredDatabaseMetadata)"
	iter := adminClient.ListDatabaseOperations(ctx, &adminpb.ListDatabaseOperationsRequest{
		Parent: instanceName,
		Filter: filter,
	})
	for {
		resp, err := iter.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			return err
		}
		metadata := &adminpb.OptimizeRestoredDatabaseMetadata{}
		if err := ptypes.UnmarshalAny(resp.Metadata, metadata); err != nil {
			return err
		}
		fmt.Fprintf(w, "Database %s restored from backup is %d%% optimized.\n",
			metadata.Name,
			metadata.Progress.ProgressPercent,
		)
	}
	return nil
}

Java

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库

static void listDatabaseOperations(
    InstanceAdminClient instanceAdminClient,
    DatabaseAdminClient dbAdminClient,
    InstanceId instanceId) {
  Instance instance = instanceAdminClient.getInstance(instanceId.getInstance());
  // Get optimize restored database operations.
  Timestamp last24Hours = Timestamp.ofTimeSecondsAndNanos(TimeUnit.SECONDS.convert(
      TimeUnit.HOURS.convert(Timestamp.now().getSeconds(), TimeUnit.SECONDS) - 24,
      TimeUnit.HOURS), 0);
  String filter = String.format("(metadata.@type:type.googleapis.com/"
                  + "google.spanner.admin.database.v1.OptimizeRestoredDatabaseMetadata) AND "
                  + "(metadata.progress.start_time > \"%s\")", last24Hours);
  for (Operation op : instance.listDatabaseOperations(Options.filter(filter)).iterateAll()) {
    try {
      OptimizeRestoredDatabaseMetadata metadata =
          op.getMetadata().unpack(OptimizeRestoredDatabaseMetadata.class);
      System.out.println(String.format(
          "Database %s restored from backup is %d%% optimized",
          metadata.getName(),
          metadata.getProgress().getProgressPercent()));
    } catch (InvalidProtocolBufferException e) {
      // The returned operation does not contain OptimizeRestoredDatabaseMetadata.
      System.err.println(e.getMessage());
    }
  }
}

Node.js

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库

// Imports the Google Cloud client library
const {Spanner, protos} = require('@google-cloud/spanner');

/**
 * TODO(developer): Uncomment the following lines before running the sample.
 */
// const projectId = 'my-project-id';
// const instanceId = 'my-instance';

// Creates a client
const spanner = new Spanner({
  projectId: projectId,
});

// Gets a reference to a Cloud Spanner instance
const instance = spanner.instance(instanceId);

// List database operations
try {
  const [databaseOperations] = await instance.getDatabaseOperations({
    filter:
      '(metadata.@type:type.googleapis.com/google.spanner.admin.database.v1.OptimizeRestoredDatabaseMetadata)',
  });
  console.log('Optimize Database Operations:');
  databaseOperations.forEach(databaseOperation => {
    const metadata =
      protos.google.spanner.admin.database.v1.OptimizeRestoredDatabaseMetadata.decode(
        databaseOperation.metadata.value
      );
    console.log(
      `Database ${metadata.name} restored from backup is ` +
        `${metadata.progress.progressPercent}% optimized.`
    );
  });
} catch (err) {
  console.error('ERROR:', err);
}

PHP

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库

use Google\Cloud\Spanner\SpannerClient;

/**
 * List all optimize restored database operations in an instance.
 * Example:
 * ```
 * list_database_operations($instanceId);
 * ```
 *
 * @param string $instanceId The Spanner instance ID.
 */
function list_database_operations($instanceId)
{
    $spanner = new SpannerClient();
    $instance = $spanner->instance($instanceId);

    // List the databases that are being optimized after a restore operation.
    $filter = '(metadata.@type:type.googleapis.com/' .
              'google.spanner.admin.database.v1.OptimizeRestoredDatabaseMetadata)';

    $operations = $instance->databaseOperations(['filter' => $filter]);

    foreach ($operations as $operation) {
        if (!$operation->done()) {
            $meta = $operation->info()['metadata'];
            $dbName = basename($meta['name']);
            $progress = $meta['progress']['progressPercent'];
            printf('Database %s restored from backup is %d%% optimized.' . PHP_EOL, $dbName, $progress);
        }
    }
}

Python

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库

def list_database_operations(instance_id):
    spanner_client = spanner.Client()
    instance = spanner_client.instance(instance_id)

    # List the progress of restore.
    filter_ = (
        "(metadata.@type:type.googleapis.com/"
        "google.spanner.admin.database.v1.OptimizeRestoredDatabaseMetadata)"
    )
    operations = instance.list_database_operations(filter_=filter_)
    for op in operations:
        print(
            "Database {} restored from backup is {}% optimized.".format(
                op.metadata.name, op.metadata.progress.progress_percent
            )
        )

Ruby

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库

# project_id  = "Your Google Cloud project ID"
# instance_id = "Your Spanner instance ID"

require "google/cloud/spanner"
require "google/cloud/spanner/admin/database"

database_admin_client = Google::Cloud::Spanner::Admin::Database.database_admin
instance_path = database_admin_client.instance_path project: project_id, instance: instance_id
jobs = database_admin_client.list_database_operations parent: instance_path,
                                                      filter: "metadata.@type:type.googleapis.com/google.spanner.admin.database.v1.OptimizeRestoredDatabaseMetadata"

jobs.each do |job|
  if job.error?
    puts job.error
  elsif job.results
    progress_percent = job.metadata.progress.progress_percent
    puts "Database #{job.results.name} restored from backup is #{progress_percent}% optimized"
  end
end

puts "List database operations with optimized database filter found #{jobs.count} jobs."

取消备份操作

以下代码示例创建备份、取消备份操作,然后轮询或等待直到备份操作为 done 状态。如果操作已成功取消,则会显示 cancelTime 和错误消息。如果备份操作在被取消之前完成,则备份将存在,在这种情况下,我们将删除备份以进行清理。

C#

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库


using Google.Cloud.Spanner.Admin.Database.V1;
using Google.Cloud.Spanner.Common.V1;
using Google.LongRunning;
using Google.Protobuf.WellKnownTypes;
using System;

public class CancelBackupOperationSample
{
    public bool CancelBackupOperation(string projectId, string instanceId, string databaseId, string backupId)
    {
        // Create the DatabaseAdminClient instance.
        DatabaseAdminClient databaseAdminClient = DatabaseAdminClient.Create();

        // Initialize backup request parameters.
        Backup backup = new Backup
        {
            DatabaseAsDatabaseName = DatabaseName.FromProjectInstanceDatabase(projectId, instanceId, databaseId),
            ExpireTime = DateTime.UtcNow.AddDays(14).ToTimestamp()
        };
        InstanceName parentAsInstanceName = InstanceName.FromProjectInstance(projectId, instanceId);

        // Make the CreateBackup request.
        Operation<Backup, CreateBackupMetadata> operation = databaseAdminClient.CreateBackup(parentAsInstanceName, backup, backupId);

        // Cancel the operation.
        operation.Cancel();

        // Poll until the long-running operation is completed in case the backup was
        // created before the operation was cancelled.
        Console.WriteLine("Waiting for the operation to finish.");
        Operation<Backup, CreateBackupMetadata> completedOperation = operation.PollUntilCompleted();

        if (!completedOperation.IsFaulted)
        {
            Console.WriteLine("The backup was created before the operation was cancelled. Please delete the backup.");
            BackupName backupAsBackupName = BackupName.FromProjectInstanceBackup(projectId, instanceId, backupId);
            databaseAdminClient.DeleteBackup(backupAsBackupName);
        }
        else
        {
            Console.WriteLine($"Create backup operation cancelled: {operation.Name}");
        }

        return completedOperation.IsFaulted;
    }
}

C++

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库

void CreateBackupAndCancel(
    google::cloud::spanner_admin::DatabaseAdminClient client,
    std::string const& project_id, std::string const& instance_id,
    std::string const& database_id, std::string const& backup_id,
    google::cloud::spanner::Timestamp expire_time) {
  google::cloud::spanner::Database database(project_id, instance_id,
                                            database_id);
  google::spanner::admin::database::v1::CreateBackupRequest request;
  request.set_parent(database.instance().FullName());
  request.set_backup_id(backup_id);
  request.mutable_backup()->set_database(database.FullName());
  *request.mutable_backup()->mutable_expire_time() =
      expire_time.get<google::protobuf::Timestamp>().value();
  auto f = client.CreateBackup(request);
  f.cancel();
  auto backup = f.get();
  if (backup) {
    auto status = client.DeleteBackup(backup->name());
    if (!status.ok()) throw std::runtime_error(status.message());
    std::cout << "Backup " << backup->name() << " was deleted.\n";
  } else {
    std::cout << "CreateBackup operation was cancelled with the message '"
              << backup.status().message() << "'.\n";
  }
}

Go

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库


import (
	"context"
	"fmt"
	"io"
	"regexp"
	"time"

	database "cloud.google.com/go/spanner/admin/database/apiv1"
	pbt "github.com/golang/protobuf/ptypes/timestamp"
	"google.golang.org/genproto/googleapis/longrunning"
	adminpb "google.golang.org/genproto/googleapis/spanner/admin/database/v1"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
)

func cancelBackup(ctx context.Context, w io.Writer, db, backupID string) error {
	matches := regexp.MustCompile("^(.+)/databases/(.+)$").FindStringSubmatch(db)
	if matches == nil || len(matches) != 3 {
		return fmt.Errorf("cancelBackup: invalid database id %q", db)
	}

	adminClient, err := database.NewDatabaseAdminClient(ctx)
	if err != nil {
		return fmt.Errorf("cancelBackup.NewDatabaseAdminClient: %v", err)
	}
	defer adminClient.Close()

	expireTime := time.Now().AddDate(0, 0, 14)
	// Create a backup.
	req := adminpb.CreateBackupRequest{
		Parent:   matches[1],
		BackupId: backupID,
		Backup: &adminpb.Backup{
			Database:   db,
			ExpireTime: &pbt.Timestamp{Seconds: expireTime.Unix(), Nanos: int32(expireTime.Nanosecond())},
		},
	}
	op, err := adminClient.CreateBackup(ctx, &req)
	if err != nil {
		return fmt.Errorf("cancelBackup.CreateBackup: %v", err)
	}

	// Cancel backup creation.
	err = adminClient.LROClient.CancelOperation(ctx, &longrunning.CancelOperationRequest{Name: op.Name()})
	if err != nil {
		return fmt.Errorf("cancelBackup.CancelOperation: %v", err)
	}

	// Cancel operations are best effort so either it will complete or be
	// cancelled.
	backup, err := op.Wait(ctx)
	if err != nil {
		if waitStatus, ok := status.FromError(err); !ok || waitStatus.Code() != codes.Canceled {
			return fmt.Errorf("cancelBackup.Wait: %v", err)
		}
	} else {
		// Backup was completed before it could be cancelled so delete the
		// unwanted backup.
		err = adminClient.DeleteBackup(ctx, &adminpb.DeleteBackupRequest{Name: backup.Name})
		if err != nil {
			return fmt.Errorf("cancelBackup.DeleteBackup: %v", err)
		}
	}

	fmt.Fprintf(w, "Backup cancelled.\n")
	return nil
}

Java

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库

static void cancelCreateBackup(
    DatabaseAdminClient dbAdminClient, DatabaseId databaseId, BackupId backupId) {
  // Set expire time to 14 days from now.
  Timestamp expireTime = Timestamp.ofTimeMicroseconds(TimeUnit.MICROSECONDS.convert(
      System.currentTimeMillis() + TimeUnit.DAYS.toMillis(14), TimeUnit.MILLISECONDS));

  // Create a backup instance.
  Backup backup =
      dbAdminClient
          .newBackupBuilder(backupId)
          .setDatabase(databaseId)
          .setExpireTime(expireTime)
          .build();
  // Start the creation of a backup.
  System.out.println("Creating backup [" + backup.getId() + "]...");
  OperationFuture<Backup, CreateBackupMetadata> op = backup.create();
  try {
    // Try to cancel the backup operation.
    System.out.println("Cancelling create backup operation for [" + backup.getId() + "]...");
    dbAdminClient.cancelOperation(op.getName());
    // Get a polling future for the running operation. This future will regularly poll the server
    // for the current status of the backup operation.
    RetryingFuture<OperationSnapshot> pollingFuture = op.getPollingFuture();
    // Wait for the operation to finish.
    // isDone will return true when the operation is complete, regardless of whether it was
    // successful or not.
    while (!pollingFuture.get().isDone()) {
      System.out.println("Waiting for the cancelled backup operation to finish...");
      Thread.sleep(TimeUnit.MILLISECONDS.convert(5, TimeUnit.SECONDS));
    }
    if (pollingFuture.get().getErrorCode() == null) {
      // Backup was created before it could be cancelled. Delete the backup.
      backup.delete();
      System.out.println("Backup operation for [" + backup.getId()
          + "] successfully finished before it could be cancelled");
    } else if (pollingFuture.get().getErrorCode().getCode() == StatusCode.Code.CANCELLED) {
      System.out.println("Backup operation for [" + backup.getId() + "] successfully cancelled");
    }
  } catch (ExecutionException e) {
    throw SpannerExceptionFactory.newSpannerException(e.getCause());
  } catch (InterruptedException e) {
    throw SpannerExceptionFactory.propagateInterrupt(e);
  }
}

Node.js

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库

// Imports the Google Cloud client library and precise date library
const {Spanner} = require('@google-cloud/spanner');

/**
 * TODO(developer): Uncomment the following lines before running the sample.
 */
// const projectId = 'my-project-id';
// const instanceId = 'my-instance';
// const databaseId = 'my-database';
// const backupId = 'my-backup';

// Creates a client
const spanner = new Spanner({
  projectId: projectId,
});

// Gets a reference to a Cloud Spanner instance and database
const instance = spanner.instance(instanceId);
const database = instance.database(databaseId);

const backup = instance.backup(backupId);

// Creates a new backup of the database
try {
  console.log(`Creating backup of database ${database.formattedName_}.`);
  const databasePath = database.formattedName_;
  // Expire backup one day in the future
  const expireTime = Date.now() + 1000 * 60 * 60 * 24;
  const [, operation] = await backup.create({
    databasePath: databasePath,
    expireTime: expireTime,
  });

  // Cancel the backup
  await operation.cancel();

  console.log('Backup cancelled.');
} catch (err) {
  console.error('ERROR:', err);
} finally {
  // Delete backup in case it got created before the cancel operation
  await backup.delete();

  // Close the database when finished.
  await database.close();
}

PHP

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库

use Google\Cloud\Spanner\SpannerClient;

/**
 * Cancel a backup operation.
 * Example:
 * ```
 * cancel_backup($instanceId, $databaseId);
 * ```
 *
 * @param string $instanceId The Spanner instance ID.
 * @param string $databaseId The Spanner database ID.
 */
function cancel_backup($instanceId, $databaseId)
{
    $spanner = new SpannerClient();
    $instance = $spanner->instance($instanceId);
    $database = $instance->database($databaseId);
    $backupId = uniqid('backup-' . $databaseId . '-cancel');

    $expireTime = new \DateTime('+14 days');
    $backup = $instance->backup($backupId);
    $operation = $backup->create($database->name(), $expireTime);
    $operation->cancel();
    print('Waiting for operation to complete ...' . PHP_EOL);
    $operation->pollUntilComplete();

    // Cancel operations are always successful regardless of whether the operation is
    // still in progress or is complete.
    printf('Cancel backup operation complete.' . PHP_EOL);

    // Operation may succeed before cancel() has been called. So we need to clean up created backup.
    if ($backup->exists()) {
        $backup->delete();
    }
}

Python

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库

def cancel_backup(instance_id, database_id, backup_id):
    spanner_client = spanner.Client()
    instance = spanner_client.instance(instance_id)
    database = instance.database(database_id)

    expire_time = datetime.utcnow() + timedelta(days=30)

    # Create a backup.
    backup = instance.backup(backup_id, database=database, expire_time=expire_time)
    operation = backup.create()

    # Cancel backup creation.
    operation.cancel()

    # Cancel operations are best effort so either it will complete or
    # be cancelled.
    while not operation.done():
        time.sleep(300)  # 5 mins

    # Deal with resource if the operation succeeded.
    if backup.exists():
        print("Backup was created before the cancel completed.")
        backup.delete()
        print("Backup deleted.")
    else:
        print("Backup creation was successfully cancelled.")

Ruby

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库

# project_id  = "Your Google Cloud project ID"
# instance_id = "Your Spanner instance ID"
# database_id = "Your Spanner database ID"
# backup_id = "Your Spanner backup ID"

require "google/cloud/spanner"
require "google/cloud/spanner/admin/database"

database_admin_client = Google::Cloud::Spanner::Admin::Database.database_admin

instance_path = database_admin_client.instance_path project: project_id, instance: instance_id

db_path = database_admin_client.database_path project: project_id,
                                              instance: instance_id,
                                              database: database_id

backup_path = database_admin_client.backup_path project: project_id,
                                                instance: instance_id,
                                                backup: backup_id

expire_time = Time.now + 14 * 24 * 3600 # 14 days from now

job = database_admin_client.create_backup parent: instance_path,
                                          backup_id: backup_id,
                                          backup: {
                                            database: db_path,
                                              expire_time: expire_time
                                          }

puts "Backup operation in progress"

job.cancel
job.wait_until_done!

begin
  backup = database_admin_client.get_backup name: backup_path
  database_admin_client.delete_backup name: backup_path if backup
rescue StandardError
  nil # no cleanup needed when a backup is not created
end
puts "#{backup_id} creation job cancelled"

列出实例中的备份

以下代码示例列出给定实例中的备份。

您可以通过提供过滤条件表达式来过滤返回备份列表(例如,按名称、版本时间或按备份过期时间过滤)。如需了解过滤语法,请参阅列出备份中的 filter 参数。

C#

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库


using Google.Cloud.Spanner.Admin.Database.V1;
using Google.Cloud.Spanner.Common.V1;
using System;
using System.Collections.Generic;

public class ListBackupsSample
{
    public IEnumerable<Backup> ListBackups(string projectId, string instanceId, string databaseId, string backupId)
    {
        // Create the DatabaseAdminClient instance.
        DatabaseAdminClient databaseAdminClient = DatabaseAdminClient.Create();

        InstanceName parentAsInstanceName = InstanceName.FromProjectInstance(projectId, instanceId);

        // List all backups.
        Console.WriteLine("All backups:");
        var allBackups = databaseAdminClient.ListBackups(parentAsInstanceName);
        PrintBackups(allBackups);

        ListBackupsRequest request = new ListBackupsRequest
        {
            ParentAsInstanceName = parentAsInstanceName,
        };

        // List backups containing backup name.
        Console.WriteLine($"Backups with backup name containing {backupId}:");
        request.Filter = $"name:{backupId}";
        var backupsWithName = databaseAdminClient.ListBackups(request);
        PrintBackups(backupsWithName);

        // List backups on a database containing name.
        Console.WriteLine($"Backups with database name containing {databaseId}:");
        request.Filter = $"database:{databaseId}";
        var backupsWithDatabaseName = databaseAdminClient.ListBackups(request);
        PrintBackups(backupsWithDatabaseName);

        // List backups that expire within 30 days.
        Console.WriteLine("Backups expiring within 30 days:");
        string expireTime = DateTime.UtcNow.AddDays(30).ToString("O");
        request.Filter = $"expire_time < \"{expireTime}\"";
        var expiringBackups = databaseAdminClient.ListBackups(request);
        PrintBackups(expiringBackups);

        // List backups with a size greater than 100 bytes.
        Console.WriteLine("Backups with size > 100 bytes:");
        request.Filter = "size_bytes > 100";
        var backupsWithSize = databaseAdminClient.ListBackups(request);
        PrintBackups(backupsWithSize);

        // List backups created in the last day that are ready.
        Console.WriteLine("Backups created within last day that are ready:");
        string createTime = DateTime.UtcNow.AddDays(-1).ToString("O");
        request.Filter = $"create_time >= \"{createTime}\" AND state:READY";
        var recentReadyBackups = databaseAdminClient.ListBackups(request);
        PrintBackups(recentReadyBackups);

        // List backups in pages.
        foreach (var page in databaseAdminClient.ListBackups(parentAsInstanceName, pageSize: 5).AsRawResponses())
        {
            PrintBackups(page);
        }

        return allBackups;
    }

    private static void PrintBackups(IEnumerable<Backup> backups)
    {
        foreach (Backup backup in backups)
        {
            Console.WriteLine($"Backup Name : {backup.Name}");
        };
    }
}

C++

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库

void ListBackups(google::cloud::spanner_admin::DatabaseAdminClient client,
                 std::string const& project_id,
                 std::string const& instance_id) {
  google::cloud::spanner::Instance in(project_id, instance_id);
  std::cout << "All backups:\n";
  for (auto const& backup : client.ListBackups(in.FullName())) {
    if (!backup) throw std::runtime_error(backup.status().message());
    std::cout << "Backup " << backup->name() << " on database "
              << backup->database() << " with size : " << backup->size_bytes()
              << " bytes.\n";
  }
}

Go

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库


import (
	"context"
	"fmt"
	"io"
	"regexp"
	"time"

	database "cloud.google.com/go/spanner/admin/database/apiv1"
	"google.golang.org/api/iterator"
	adminpb "google.golang.org/genproto/googleapis/spanner/admin/database/v1"
)

func listBackups(ctx context.Context, w io.Writer, db, backupID string) error {
	adminClient, err := database.NewDatabaseAdminClient(ctx)
	if err != nil {
		return err
	}
	defer adminClient.Close()

	matches := regexp.MustCompile("^(.*)/databases/(.*)$").FindStringSubmatch(db)
	if matches == nil || len(matches) != 3 {
		return fmt.Errorf("Invalid database id %s", db)
	}
	instanceName := matches[1]

	printBackups := func(iter *database.BackupIterator) error {
		for {
			resp, err := iter.Next()
			if err == iterator.Done {
				return nil
			}
			if err != nil {
				return err
			}
			fmt.Fprintf(w, "Backup %s\n", resp.Name)
		}
	}

	var iter *database.BackupIterator
	var filter string
	// List all backups.
	iter = adminClient.ListBackups(ctx, &adminpb.ListBackupsRequest{
		Parent: instanceName,
	})
	if err := printBackups(iter); err != nil {
		return err
	}

	// List all backups that contain a name.
	iter = adminClient.ListBackups(ctx, &adminpb.ListBackupsRequest{
		Parent: instanceName,
		Filter: "name:" + backupID,
	})
	if err := printBackups(iter); err != nil {
		return err
	}

	// List all backups that expire before a timestamp.
	expireTime := time.Now().AddDate(0, 0, 30)
	filter = fmt.Sprintf(`expire_time < "%s"`, expireTime.Format(time.RFC3339))
	iter = adminClient.ListBackups(ctx, &adminpb.ListBackupsRequest{
		Parent: instanceName,
		Filter: filter,
	})
	if err := printBackups(iter); err != nil {
		return err
	}

	// List all backups for a database that contains a name.
	iter = adminClient.ListBackups(ctx, &adminpb.ListBackupsRequest{
		Parent: instanceName,
		Filter: "database:" + db,
	})
	if err := printBackups(iter); err != nil {
		return err
	}

	// List all backups with a size greater than some bytes.
	iter = adminClient.ListBackups(ctx, &adminpb.ListBackupsRequest{
		Parent: instanceName,
		Filter: "size_bytes > 100",
	})
	if err := printBackups(iter); err != nil {
		return err
	}

	// List backups that were created after a timestamp that are also ready.
	createTime := time.Now().AddDate(0, 0, -1)
	filter = fmt.Sprintf(
		`create_time >= "%s" AND state:READY`,
		createTime.Format(time.RFC3339),
	)
	iter = adminClient.ListBackups(ctx, &adminpb.ListBackupsRequest{
		Parent: instanceName,
		Filter: filter,
	})
	if err := printBackups(iter); err != nil {
		return err
	}

	// List backups with pagination.
	request := &adminpb.ListBackupsRequest{
		Parent:   instanceName,
		PageSize: 10,
	}
	for {
		iter = adminClient.ListBackups(ctx, request)
		if err := printBackups(iter); err != nil {
			return err
		}
		pageToken := iter.PageInfo().Token
		if pageToken == "" {
			break
		} else {
			request.PageToken = pageToken
		}
	}

	fmt.Fprintf(w, "Backups listed.\n")
	return nil
}

Java

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库

static void listBackups(
    InstanceAdminClient instanceAdminClient, DatabaseId databaseId, BackupId backupId) {
  Instance instance = instanceAdminClient.getInstance(databaseId.getInstanceId().getInstance());
  // List all backups.
  System.out.println("All backups:");
  for (Backup backup : instance.listBackups().iterateAll()) {
    System.out.println(backup);
  }

  // List all backups with a specific name.
  System.out.println(
      String.format("All backups with backup name containing \"%s\":", backupId.getBackup()));
  for (Backup backup : instance.listBackups(
      Options.filter(String.format("name:%s", backupId.getBackup()))).iterateAll()) {
    System.out.println(backup);
  }

  // List all backups for databases whose name contains a certain text.
  System.out.println(
      String.format(
          "All backups for databases with a name containing \"%s\":",
          databaseId.getDatabase()));
  for (Backup backup : instance.listBackups(
      Options.filter(String.format("database:%s", databaseId.getDatabase()))).iterateAll()) {
    System.out.println(backup);
  }

  // List all backups that expire before a certain time.
  Timestamp expireTime = Timestamp.ofTimeMicroseconds(TimeUnit.MICROSECONDS.convert(
      System.currentTimeMillis() + TimeUnit.DAYS.toMillis(30), TimeUnit.MILLISECONDS));
  System.out.println(String.format("All backups that expire before %s:", expireTime.toString()));
  for (Backup backup :
      instance.listBackups(
          Options.filter(String.format("expire_time < \"%s\"", expireTime.toString())))
      .iterateAll()) {
    System.out.println(backup);
  }

  // List all backups with size greater than a certain number of bytes.
  System.out.println("All backups with size greater than 100 bytes:");
  for (Backup backup : instance.listBackups(Options.filter("size_bytes > 100")).iterateAll()) {
    System.out.println(backup);
  }

  // List all backups with a create time after a certain timestamp and that are also ready.
  Timestamp createTime = Timestamp.ofTimeMicroseconds(TimeUnit.MICROSECONDS.convert(
      System.currentTimeMillis() - TimeUnit.DAYS.toMillis(1), TimeUnit.MILLISECONDS));
  System.out.println(
      String.format(
          "All databases created after %s and that are ready:", createTime.toString()));
  for (Backup backup :
      instance
          .listBackups(Options.filter(
              String.format("create_time >= \"%s\" AND state:READY", createTime.toString())))
          .iterateAll()) {
    System.out.println(backup);
  }

  // List backups using pagination.
  System.out.println("All backups, listed using pagination:");
  Page<Backup> page = instance.listBackups(Options.pageSize(10));
  while (true) {
    for (Backup backup : page.getValues()) {
      System.out.println(backup);
    }
    if (!page.hasNextPage()) {
      break;
    }
    page = page.getNextPage();
  }
}

Node.js

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库

// Imports the Google Cloud client library
const {Spanner} = require('@google-cloud/spanner');

/**
 * TODO(developer): Uncomment the following lines before running the sample.
 */
// const projectId = 'my-project-id';
// const instanceId = 'my-instance';
// const databaseId = 'my-database';
// const backupId = 'my-backup';

// Creates a client
const spanner = new Spanner({
  projectId: projectId,
});

// Gets a reference to a Cloud Spanner instance
const instance = spanner.instance(instanceId);

try {
  // List all backups
  const [allBackups] = await instance.getBackups();
  console.log('All backups:');
  allBackups.forEach(backup => {
    console.log(backup.id);
  });

  // List backups filtered by backup name
  const [backupsByName] = await instance.getBackups({
    filter: `Name:${backupId}`,
  });
  console.log('Backups matching backup name:');
  backupsByName.forEach(backup => {
    console.log(backup.id);
  });

  // List backups expiring within 30 days
  const expireTime = new Date();
  expireTime.setDate(expireTime.getDate() + 30);
  const [backupsByExpiry] = await instance.getBackups({
    filter: `expire_time < "${expireTime.toISOString()}"`,
  });
  console.log('Backups expiring within 30 days:');
  backupsByExpiry.forEach(backup => {
    console.log(backup.id);
  });

  // List backups filtered by database name
  const [backupsByDbName] = await instance.getBackups({
    filter: `Database:${databaseId}`,
  });
  console.log('Backups matching database name:');
  backupsByDbName.forEach(backup => {
    console.log(backup.id);
  });

  // List backups filtered by backup size
  const [backupsBySize] = await instance.getBackups({
    filter: 'size_bytes > 100',
  });
  console.log('Backups filtered by size:');
  backupsBySize.forEach(backup => {
    console.log(backup.id);
  });

  // List backups that are ready that were created after a certain time
  const createTime = new Date();
  createTime.setDate(createTime.getDate() - 1);
  const [backupsByCreateTime] = await instance.getBackups({
    filter: `(state:READY) AND (create_time >= "${createTime.toISOString()}")`,
  });
  console.log('Ready backups filtered by create time:');
  backupsByCreateTime.forEach(backup => {
    console.log(backup.id);
  });

  // List backups using pagination
  let getBackupsOptions = {
    pageSize: 3,
    gaxOptions: {autoPaginate: false},
  };
  console.log('Get backups paginated:');
  do {
    const [backups, nextQuery] = await instance.getBackups(getBackupsOptions);
    backups.forEach(backup => {
      console.log(backup.id);
    });
    getBackupsOptions = nextQuery;
  } while (getBackupsOptions);
} catch (err) {
  console.error('ERROR:', err);
}

PHP

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库

use Google\Cloud\Spanner\SpannerClient;

/**
 * List backups in an instance.
 * Example:
 * ```
 * list_backups($instanceId, $databaseId);
 * ```
 *
 * @param string $instanceId The Spanner instance ID.
 */
function list_backups($instanceId)
{
    $spanner = new SpannerClient();
    $instance = $spanner->instance($instanceId);

    // List all backups.
    print('All backups:' . PHP_EOL);
    foreach ($instance->backups() as $backup) {
        print('  ' . basename($backup->name()) . PHP_EOL);
    }

    // List all backups that contain a name.
    $backupName = 'backup-test-';
    print("All backups with name containing \"$backupName\":" . PHP_EOL);
    $filter = "name:$backupName";
    foreach ($instance->backups(['filter' => $filter]) as $backup) {
        print('  ' . basename($backup->name()) . PHP_EOL);
    }

    // List all backups for a database that contains a name.
    $databaseId = 'test-';
    print("All backups for a database which name contains \"$databaseId\":" . PHP_EOL);
    $filter = "database:$databaseId";
    foreach ($instance->backups(['filter' => $filter]) as $backup) {
        print('  ' . basename($backup->name()) . PHP_EOL);
    }

    // List all backups that expire before a timestamp.
    $expireTime = $spanner->timestamp(new \DateTime('+30 days'));
    print("All backups that expire before $expireTime:" . PHP_EOL);
    $filter = "expire_time < \"$expireTime\"";
    foreach ($instance->backups(['filter' => $filter]) as $backup) {
        print('  ' . basename($backup->name()) . PHP_EOL);
    }

    // List all backups with a size greater than some bytes.
    $size = 500;
    print("All backups with size greater than $size bytes:" . PHP_EOL);
    $filter = "size_bytes > $size";
    foreach ($instance->backups(['filter' => $filter]) as $backup) {
        print('  ' . basename($backup->name()) . PHP_EOL);
    }

    // List backups that were created after a timestamp that are also ready.
    $createTime = $spanner->timestamp(new \DateTime('-1 day'));
    print("All backups created after $createTime:" . PHP_EOL);
    $filter = "create_time >= \"$createTime\" AND state:READY";
    foreach ($instance->backups(['filter' => $filter]) as $backup) {
        print('  ' . basename($backup->name()) . PHP_EOL);
    }

    // List backups with pagination.
    print('All backups with pagination:' . PHP_EOL);
    $pages = $instance->backups(['pageSize' => 2])->iterateByPage();
    foreach ($pages as $pageNumber => $page) {
        print("All backups, page $pageNumber:" . PHP_EOL);
        foreach ($page as $backup) {
            print('  ' . basename($backup->name()) . PHP_EOL);
        }
    }
}

Python

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库

def list_backups(instance_id, database_id, backup_id):
    spanner_client = spanner.Client()
    instance = spanner_client.instance(instance_id)

    # List all backups.
    print("All backups:")
    for backup in instance.list_backups():
        print(backup.name)

    # List all backups that contain a name.
    print('All backups with backup name containing "{}":'.format(backup_id))
    for backup in instance.list_backups(filter_="name:{}".format(backup_id)):
        print(backup.name)

    # List all backups for a database that contains a name.
    print('All backups with database name containing "{}":'.format(database_id))
    for backup in instance.list_backups(filter_="database:{}".format(database_id)):
        print(backup.name)

    # List all backups that expire before a timestamp.
    expire_time = datetime.utcnow().replace(microsecond=0) + timedelta(days=30)
    print(
        'All backups with expire_time before "{}-{}-{}T{}:{}:{}Z":'.format(
            *expire_time.timetuple()
        )
    )
    for backup in instance.list_backups(
        filter_='expire_time < "{}-{}-{}T{}:{}:{}Z"'.format(*expire_time.timetuple())
    ):
        print(backup.name)

    # List all backups with a size greater than some bytes.
    print("All backups with backup size more than 100 bytes:")
    for backup in instance.list_backups(filter_="size_bytes > 100"):
        print(backup.name)

    # List backups that were created after a timestamp that are also ready.
    create_time = datetime.utcnow().replace(microsecond=0) - timedelta(days=1)
    print(
        'All backups created after "{}-{}-{}T{}:{}:{}Z" and are READY:'.format(
            *create_time.timetuple()
        )
    )
    for backup in instance.list_backups(
        filter_='create_time >= "{}-{}-{}T{}:{}:{}Z" AND state:READY'.format(
            *create_time.timetuple()
        )
    ):
        print(backup.name)

    print("All backups with pagination")
    # If there are multiple pages, additional ``ListBackup``
    # requests will be made as needed while iterating.
    for backup in instance.list_backups(page_size=2):
        print(backup.name)

Ruby

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库

# project_id  = "Your Google Cloud project ID"
# instance_id = "Your Spanner instance ID"
# backup_id = "Your Spanner database backup ID"
# database_id = "Your Spanner databaseID"

require "google/cloud/spanner"
require "google/cloud/spanner/admin/database"

database_admin_client = Google::Cloud::Spanner::Admin::Database.database_admin
instance_path = database_admin_client.instance_path project: project_id, instance: instance_id

puts "All backups"
database_admin_client.list_backups(parent: instance_path).each do |backup|
  puts backup.name
end

puts "All backups with backup name containing \"#{backup_id}\":"
database_admin_client.list_backups(parent: instance_path, filter: "name:#{backup_id}").each do |backup|
  puts backup.name
end

puts "All backups for databases with a name containing \"#{database_id}\":"
database_admin_client.list_backups(parent: instance_path, filter: "database:#{database_id}").each do |backup|
  puts backup.name
end

puts "All backups that expire before a timestamp:"
expire_time = Time.now + 30 * 24 * 3600 # 30 days from now
database_admin_client.list_backups(parent: instance_path, filter: "expire_time < \"#{expire_time.iso8601}\"").each do |backup|
  puts backup.name
end

puts "All backups with a size greater than 500 bytes:"
database_admin_client.list_backups(parent: instance_path, filter: "size_bytes >= 500").each do |backup|
  puts backup.name
end

puts "All backups that were created after a timestamp that are also ready:"
create_time = Time.now - 24 * 3600 # From 1 day ago
database_admin_client.list_backups(parent: instance_path, filter: "create_time >= \"#{create_time.iso8601}\" AND state:READY").each do |backup|
  puts backup.name
end

puts "All backups with pagination:"
list = database_admin_client.list_backups parent: instance_path, page_size: 5
list.each do |backup|
  puts backup.name
end

更新备份

以下代码示例检索备份的过期时间并进行延长。

C#

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库


using Google.Cloud.Spanner.Admin.Database.V1;
using Google.Protobuf.WellKnownTypes;
using System;

public class UpdateBackupSample
{
    public Backup UpdateBackup(string projectId, string instanceId, string backupId)
    {
        // Create the DatabaseAdminClient instance.
        DatabaseAdminClient databaseAdminClient = DatabaseAdminClient.Create();

        // Retrieve existing backup.
        BackupName backupName = BackupName.FromProjectInstanceBackup(projectId, instanceId, backupId);
        Backup backup = databaseAdminClient.GetBackup(backupName);

        // Add 1 hour to the existing ExpireTime.
        backup.ExpireTime = backup.ExpireTime.ToDateTime().AddHours(1).ToTimestamp();

        UpdateBackupRequest backupUpdateRequest = new UpdateBackupRequest
        {
            UpdateMask = new FieldMask
            {
                Paths = { "expire_time" }
            },
            Backup = backup
        };

        // Make the UpdateBackup requests.
        var updatedBackup = databaseAdminClient.UpdateBackup(backupUpdateRequest);

        Console.WriteLine($"Updated Backup ExpireTime: {updatedBackup.ExpireTime}");

        return updatedBackup;
    }
}

C++

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库

void UpdateBackup(google::cloud::spanner_admin::DatabaseAdminClient client,
                  std::string const& project_id, std::string const& instance_id,
                  std::string const& backup_id,
                  google::cloud::spanner::Timestamp expire_time) {
  google::cloud::spanner::Backup backup_name(
      google::cloud::spanner::Instance(project_id, instance_id), backup_id);
  google::spanner::admin::database::v1::UpdateBackupRequest request;
  request.mutable_backup()->set_name(backup_name.FullName());
  *request.mutable_backup()->mutable_expire_time() =
      expire_time.get<google::protobuf::Timestamp>().value();
  request.mutable_update_mask()->add_paths("expire_time");
  auto backup = client.UpdateBackup(request);
  if (!backup) throw std::runtime_error(backup.status().message());
  std::cout
      << "Backup " << backup->name() << " updated to expire at "
      << google::cloud::spanner::MakeTimestamp(backup->expire_time()).value()
      << ".\n";
}

Go

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库


import (
	"context"
	"fmt"
	"io"
	"regexp"
	"time"

	database "cloud.google.com/go/spanner/admin/database/apiv1"
	pbts "github.com/golang/protobuf/ptypes"
	adminpb "google.golang.org/genproto/googleapis/spanner/admin/database/v1"
	"google.golang.org/genproto/protobuf/field_mask"
)

func updateBackup(ctx context.Context, w io.Writer, db, backupID string) error {
	adminClient, err := database.NewDatabaseAdminClient(ctx)
	if err != nil {
		return err
	}
	defer adminClient.Close()

	matches := regexp.MustCompile("^(.*)/databases/(.*)$").FindStringSubmatch(db)
	if matches == nil || len(matches) != 3 {
		return fmt.Errorf("Invalid database id %s", db)
	}
	backupName := matches[1] + "/backups/" + backupID

	backup, err := adminClient.GetBackup(ctx, &adminpb.GetBackupRequest{Name: backupName})
	if err != nil {
		return err
	}

	// Expire time must be within 366 days of the create time of the backup.
	expireTime := time.Unix(backup.CreateTime.Seconds, int64(backup.CreateTime.Nanos)).AddDate(0, 0, 30)
	expirespb, err := pbts.TimestampProto(expireTime)
	if err != nil {
		return err
	}

	_, err = adminClient.UpdateBackup(ctx, &adminpb.UpdateBackupRequest{
		Backup: &adminpb.Backup{
			Name:       backupName,
			ExpireTime: expirespb,
		},
		UpdateMask: &field_mask.FieldMask{Paths: []string{"expire_time"}},
	})
	if err != nil {
		return err
	}

	fmt.Fprintf(w, "Updated backup %s\n", backupID)
	return nil
}

Java

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库

static void updateBackup(DatabaseAdminClient dbAdminClient, BackupId backupId) {
  // Get current backup metadata.
  Backup backup = dbAdminClient.newBackupBuilder(backupId).build().reload();
  // Add 30 days to the expire time.
  // Expire time must be within 366 days of the create time of the backup.
  Timestamp expireTime =
      Timestamp.ofTimeMicroseconds(
          TimeUnit.SECONDS.toMicros(backup.getExpireTime().getSeconds())
              + TimeUnit.NANOSECONDS.toMicros(backup.getExpireTime().getNanos())
              + TimeUnit.DAYS.toMicros(30L));
  System.out.println(String.format(
      "Updating expire time of backup [%s] to %s...",
      backupId.toString(),
      LocalDateTime.ofEpochSecond(
          expireTime.getSeconds(),
          expireTime.getNanos(),
          OffsetDateTime.now().getOffset()).toString()));

  // Update expire time.
  backup = backup.toBuilder().setExpireTime(expireTime).build();
  backup.updateExpireTime();
  System.out.println("Updated backup [" + backupId + "]");
}

Node.js

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库

// Imports the Google Cloud client library and precise date library
const {Spanner} = require('@google-cloud/spanner');
const {PreciseDate} = require('@google-cloud/precise-date');

/**
 * TODO(developer): Uncomment the following lines before running the sample.
 */
// const projectId = 'my-project-id';
// const instanceId = 'my-instance';
// const backupId = 'my-backup';

// Creates a client
const spanner = new Spanner({
  projectId: projectId,
});

// Gets a reference to a Cloud Spanner instance and backup
const instance = spanner.instance(instanceId);
const backup = instance.backup(backupId);

// Read backup metadata and update expiry time
try {
  const currentExpireTime = await backup.getExpireTime();
  const newExpireTime = new PreciseDate(currentExpireTime);
  newExpireTime.setDate(newExpireTime.getDate() + 30);
  console.log(
    `Backup ${backupId} current expire time: ${currentExpireTime.toISOString()}`
  );
  console.log(`Updating expire time to ${newExpireTime.toISOString()}`);
  await backup.updateExpireTime(newExpireTime);
  console.log('Expire time updated.');
} catch (err) {
  console.error('ERROR:', err);
}

PHP

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库

use Google\Cloud\Spanner\SpannerClient;

/**
 * Update the backup expire time.
 * Example:
 * ```
 * update_backup($instanceId, $backupId);
 * ```
 * @param string $instanceId The Spanner instance ID.
 * @param string $backupId The Spanner backup ID.
 */
function update_backup($instanceId, $backupId)
{
    $spanner = new SpannerClient();
    $instance = $spanner->instance($instanceId);
    $backup = $instance->backup($backupId);

    // Expire time must be within 366 days of the create time of the backup.
    $newTimestamp = new \DateTime('+30 days');
    $backup->updateExpireTime($newTimestamp);

    print("Backup $backupId new expire time: " . $backup->info()['expireTime'] . PHP_EOL);
}

Python

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库

def update_backup(instance_id, backup_id):
    spanner_client = spanner.Client()
    instance = spanner_client.instance(instance_id)
    backup = instance.backup(backup_id)
    backup.reload()

    # Expire time must be within 366 days of the create time of the backup.
    old_expire_time = backup.expire_time
    new_expire_time = old_expire_time + timedelta(days=30)
    backup.update_expire_time(new_expire_time)
    print(
        "Backup {} expire time was updated from {} to {}.".format(
            backup.name, old_expire_time, new_expire_time
        )
    )

Ruby

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库

# project_id  = "Your Google Cloud project ID"
# instance_id = "Your Spanner instance ID"
# backup_id = "Your Spanner backup ID"

require "google/cloud/spanner"
require "google/cloud/spanner/admin/database"

database_admin_client = Google::Cloud::Spanner::Admin::Database.database_admin
instance_path = database_admin_client.instance_path project: project_id, instance: instance_id
backup_path = database_admin_client.backup_path project: project_id,
                                                instance: instance_id,
                                                backup: backup_id
backup = database_admin_client.get_backup name: backup_path
backup.expire_time = Time.now + 60 * 24 * 3600 # Extending the expiry time by 60 days from now.
database_admin_client.update_backup backup: backup,
                                    update_mask: { paths: ["expire_time"] }

puts "Expiration time updated: #{backup.expire_time}"

删除备份

以下代码示例删除备份并验证其是否已删除。删除进行中的备份将移除备份资源并取消长时间运行的备份操作。

C#

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库


using Google.Cloud.Spanner.Admin.Database.V1;
using System;

public class DeleteBackupSample
{
    public void DeleteBackup(string projectId, string instanceId, string backupId)
    {
        // Create the DatabaseAdminClient instance.
        DatabaseAdminClient databaseAdminClient = DatabaseAdminClient.Create();

        // Make the DeleteBackup request.
        BackupName backupName = BackupName.FromProjectInstanceBackup(projectId, instanceId, backupId);
        databaseAdminClient.DeleteBackup(backupName);

        Console.WriteLine("Backup deleted successfully.");
    }
}

C++

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库

void DeleteBackup(google::cloud::spanner_admin::DatabaseAdminClient client,
                  std::string const& project_id, std::string const& instance_id,
                  std::string const& backup_id) {
  google::cloud::spanner::Backup backup(
      google::cloud::spanner::Instance(project_id, instance_id), backup_id);
  auto status = client.DeleteBackup(backup.FullName());
  if (!status.ok()) throw std::runtime_error(status.message());
  std::cout << "Backup " << backup.FullName() << " was deleted.\n";
}

Go

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库


import (
	"context"
	"fmt"
	"io"
	"regexp"

	database "cloud.google.com/go/spanner/admin/database/apiv1"
	adminpb "google.golang.org/genproto/googleapis/spanner/admin/database/v1"
)

func deleteBackup(ctx context.Context, w io.Writer, db, backupID string) error {
	adminClient, err := database.NewDatabaseAdminClient(ctx)
	if err != nil {
		return err
	}
	defer adminClient.Close()

	matches := regexp.MustCompile("^(.*)/databases/(.*)$").FindStringSubmatch(db)
	if matches == nil || len(matches) != 3 {
		return fmt.Errorf("Invalid database id %s", db)
	}
	backupName := matches[1] + "/backups/" + backupID
	// Delete the backup.
	err = adminClient.DeleteBackup(ctx, &adminpb.DeleteBackupRequest{Name: backupName})
	if err != nil {
		return err
	}
	fmt.Fprintf(w, "Deleted backup %s\n", backupID)
	return nil
}

Java

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库

static void deleteBackup(DatabaseAdminClient dbAdminClient, BackupId backupId) {
  Backup backup = dbAdminClient.newBackupBuilder(backupId).build();
  // Delete the backup.
  System.out.println("Deleting backup [" + backupId + "]...");
  backup.delete();
  // Verify that the backup is deleted.
  if (backup.exists()) {
    System.out.println("Delete backup [" + backupId + "] failed");
    throw new RuntimeException("Delete backup [" + backupId + "] failed");
  } else {
    System.out.println("Deleted backup [" + backupId + "]");
  }
}

Node.js

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库

// Imports the Google Cloud client library
const {Spanner} = require('@google-cloud/spanner');

/**
 * TODO(developer): Uncomment the following lines before running the sample.
 */
// const projectId = 'my-project-id';
// const instanceId = 'my-instance';
// const databaseId = 'my-database';
// const backupId = 'my-backup';

// Creates a client
const spanner = new Spanner({
  projectId: projectId,
});

// Gets a reference to a Cloud Spanner instance and backup
const instance = spanner.instance(instanceId);
const backup = instance.backup(backupId);

// Delete the backup
console.log(`Deleting backup ${backupId}.`);
await backup.delete();

// Verify backup no longer exists
const exists = await backup.exists();
if (exists) {
  console.error('Error: backup still exists.');
} else {
  console.log('Backup deleted.');
}

PHP

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库

use Google\Cloud\Spanner\SpannerClient;

/**
 * Delete a backup.
 * Example:
 * ```
 * delete_backup($instanceId, $backupId);
 * ```
 * @param string $instanceId The Spanner instance ID.
 * @param string $backupId The Spanner backup ID.
 */
function delete_backup($instanceId, $backupId)
{
    $spanner = new SpannerClient();
    $instance = $spanner->instance($instanceId);
    $backup = $instance->backup($backupId);
    $backupName = $backup->name();
    $backup->delete();
    print("Backup $backupName deleted" . PHP_EOL);
}

Python

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库

def delete_backup(instance_id, backup_id):
    spanner_client = spanner.Client()
    instance = spanner_client.instance(instance_id)
    backup = instance.backup(backup_id)
    backup.reload()

    # Wait for databases that reference this backup to finish optimizing.
    while backup.referencing_databases:
        time.sleep(30)
        backup.reload()

    # Delete the backup.
    backup.delete()

    # Verify that the backup is deleted.
    assert backup.exists() is False
    print("Backup {} has been deleted.".format(backup.name))

Ruby

如需了解如何安装和使用 Cloud Spanner 客户端库,请参阅 Cloud Spanner 客户端库

# project_id  = "Your Google Cloud project ID"
# instance_id = "Your Spanner instance ID"
# backup_id = "Your Spanner backup ID"

require "google/cloud/spanner"
require "google/cloud/spanner/admin/database"

database_admin_client = Google::Cloud::Spanner::Admin::Database.database_admin
instance_path = database_admin_client.instance_path project: project_id, instance: instance_id
backup_path = database_admin_client.backup_path project: project_id,
                                                instance: instance_id,
                                                backup: backup_id

database_admin_client.delete_backup name: backup_path
puts "Backup #{backup_id} deleted"