创建和管理数据库

本页面介绍了如何管理 Spanner database,包括如何创建数据库、 数据库选项和删除数据库。如需了解如何更新数据库架构,请参阅进行架构更新

如需练习创建数据库并使用示例数据加载数据库,请参阅 您的第一个数据库 Codelab

创建数据库

以下示例展示了如何在现有实例中创建数据库。

对于 GoogleSQL 方言数据库,您可以定义 schema(在创建数据库时创建),或者 创建数据库之后对于 PostgreSQL 方言数据库,您必须 定义架构

架构是使用数据库定义语言定义的, 对于 GoogleSQLPostgreSQL。请参阅以下链接 如需详细了解如何创建和更新架构,请参阅以下内容:

创建数据库后,您可以保护重要的数据库 来保护您的应用和服务。对于 如需了解详情,请参阅防止意外删除数据库

控制台

  1. 前往 Google Cloud 控制台中的实例页面。

    实例

  2. 选择要在其中创建数据库的实例。

  3. 点击创建数据库

  4. 输入以下值:

    • 要在 Google Cloud 控制台中显示的数据库名称
    • 要用于此数据库的方言
    • 对于 GoogleSQL 方言数据库,您可以选择提供一组 DDL 语句, 定义您的架构。使用 使用 DDL 模板预填充通用元素。如果 DDL 语句,则 Google Cloud 控制台会在出现以下情况时返回错误: 您可以尝试创建数据库
    • (可选)选择要用于客户管理的加密密钥 此数据库。
  5. 点击创建以创建数据库。

gcloud

使用 gcloud spanner databases create 命令。

gcloud spanner databases create DATABASE \
  --instance=INSTANCE \
  [--async] \
  [--database-dialect=DATABASE_DIALECT] \
  [--ddl=DDL] \
  [--ddl-file=DDL_FILE] \
  [--kms-key=KMS_KEY : --kms-keyring=KMS_KEYRING --kms-location=KMS_LOCATION --kms-project=KMS_PROJECT] \
  [GCLOUD_WIDE_FLAG …]

以下选项为必需:

DATABASE
数据库的 ID 或 数据库。如果指定完全限定的标识符, --instance 标志可以省略。
--instance=INSTANCE
数据库的 Spanner 实例。

以下选项为可选:

--async
立即返回,无需等待正在进行的操作 操作完成。
--database-dialect=DATABASE_DIALECT
Spanner 数据库的 SQL 方言。必须为 以下各项中的一项:POSTGRESQLGOOGLE_STANDARD_SQL
--ddl=DDL
要运行的以英文分号分隔的 DDL(数据定义语言)语句 创建 Deployment 清单如果执行任何 语句,则不会创建数据库。在以下情况下,系统会忽略此标志: 已设置 --ddl_file。PostgreSQL 方言数据库不支持。
--ddl-file=DDL_FILE
包含以英文分号分隔的文件的路径 在新映像中运行的 DDL(数据定义语言)语句 数据库。如果有任何语句出现错误,数据库会 未创建。如果设置了 --ddl_file,则 --ddl 已忽略。PostgreSQL 方言数据库不支持。

如果您指定了要使用的 Cloud Key Management Service 密钥 创建数据库时,请添加以下选项:

--kms-key=KMS_KEY
密钥的 ID 或密钥的完全限定标识符。

如果此字段中的任何其他参数 。如果 提供的是完全限定的标识符

--kms-keyring=KMS_KEYRING
密钥的 Cloud KMS 密钥环 ID。
--kms-location=KMS_LOCATION
密钥的 Google Cloud 位置。
--kms-project=KMS_PROJECT
密钥的 Google Cloud 项目 ID。

客户端 (GoogleSQL)

C++

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

如需向 Spanner 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为本地开发环境设置身份验证

void CreateDatabase(google::cloud::spanner_admin::DatabaseAdminClient client,
                    std::string const& project_id,
                    std::string const& instance_id,
                    std::string const& database_id) {
  google::cloud::spanner::Database database(project_id, instance_id,
                                            database_id);
  google::spanner::admin::database::v1::CreateDatabaseRequest request;
  request.set_parent(database.instance().FullName());
  request.set_create_statement("CREATE DATABASE `" + database.database_id() +
                               "`");
  request.add_extra_statements(R"""(
      CREATE TABLE Singers (
          SingerId   INT64 NOT NULL,
          FirstName  STRING(1024),
          LastName   STRING(1024),
          SingerInfo BYTES(MAX),
          FullName   STRING(2049)
              AS (ARRAY_TO_STRING([FirstName, LastName], " ")) STORED
      ) PRIMARY KEY (SingerId))""");
  request.add_extra_statements(R"""(
      CREATE TABLE Albums (
          SingerId     INT64 NOT NULL,
          AlbumId      INT64 NOT NULL,
          AlbumTitle   STRING(MAX)
      ) PRIMARY KEY (SingerId, AlbumId),
          INTERLEAVE IN PARENT Singers ON DELETE CASCADE)""");
  auto db = client.CreateDatabase(request).get();
  if (!db) throw std::move(db).status();
  std::cout << "Database " << db->name() << " created.\n";
}

Go

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

如需向 Spanner 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为本地开发环境设置身份验证

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

	database "cloud.google.com/go/spanner/admin/database/apiv1"
	adminpb "cloud.google.com/go/spanner/admin/database/apiv1/databasepb"
)

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

	adminClient, err := database.NewDatabaseAdminClient(ctx)
	if err != nil {
		return err
	}
	defer adminClient.Close()

	op, err := adminClient.CreateDatabase(ctx, &adminpb.CreateDatabaseRequest{
		Parent:          matches[1],
		CreateStatement: "CREATE DATABASE `" + matches[2] + "`",
		ExtraStatements: []string{
			`CREATE TABLE Singers (
				SingerId   INT64 NOT NULL,
				FirstName  STRING(1024),
				LastName   STRING(1024),
				SingerInfo BYTES(MAX),
				FullName   STRING(2048) AS (
					ARRAY_TO_STRING([FirstName, LastName], " ")
				) STORED
			) PRIMARY KEY (SingerId)`,
			`CREATE TABLE Albums (
				SingerId     INT64 NOT NULL,
				AlbumId      INT64 NOT NULL,
				AlbumTitle   STRING(MAX)
			) PRIMARY KEY (SingerId, AlbumId),
			INTERLEAVE IN PARENT Singers ON DELETE CASCADE`,
		},
	})
	if err != nil {
		return err
	}
	if _, err := op.Wait(ctx); err != nil {
		return err
	}
	fmt.Fprintf(w, "Created database [%s]\n", db)
	return nil
}

Java

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

如需向 Spanner 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为本地开发环境设置身份验证


import com.google.cloud.spanner.SpannerException;
import com.google.cloud.spanner.SpannerExceptionFactory;
import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient;
import com.google.common.collect.ImmutableList;
import com.google.spanner.admin.database.v1.CreateDatabaseRequest;
import com.google.spanner.admin.database.v1.Database;
import java.io.IOException;
import java.util.concurrent.ExecutionException;

public class CreateDatabaseWithDefaultLeaderSample {

  static void createDatabaseWithDefaultLeader() throws IOException {
    // TODO(developer): Replace these variables before running the sample.
    final String instanceName = "projects/my-project/instances/my-instance-id";
    final String databaseId = "my-database-name";
    final String defaultLeader = "my-default-leader";
    createDatabaseWithDefaultLeader(instanceName, databaseId, defaultLeader);
  }

  static void createDatabaseWithDefaultLeader(String instanceName, String databaseId,
      String defaultLeader) throws IOException {
    try (DatabaseAdminClient databaseAdminClient = DatabaseAdminClient.create()) {
      Database createdDatabase =
          databaseAdminClient.createDatabaseAsync(
              CreateDatabaseRequest.newBuilder()
                  .setParent(instanceName)
                  .setCreateStatement("CREATE DATABASE `" + databaseId + "`")
                  .addAllExtraStatements(
                      ImmutableList.of("CREATE TABLE Singers ("
                              + "  SingerId   INT64 NOT NULL,"
                              + "  FirstName  STRING(1024),"
                              + "  LastName   STRING(1024),"
                              + "  SingerInfo BYTES(MAX)"
                              + ") PRIMARY KEY (SingerId)",
                          "CREATE TABLE Albums ("
                              + "  SingerId     INT64 NOT NULL,"
                              + "  AlbumId      INT64 NOT NULL,"
                              + "  AlbumTitle   STRING(MAX)"
                              + ") PRIMARY KEY (SingerId, AlbumId),"
                              + "  INTERLEAVE IN PARENT Singers ON DELETE CASCADE",
                          "ALTER DATABASE " + "`" + databaseId + "`"
                              + " SET OPTIONS ( default_leader = '" + defaultLeader + "' )"))
                  .build()).get();
      System.out.println("Created database [" + createdDatabase.getName() + "]");
      System.out.println("\tDefault leader: " + createdDatabase.getDefaultLeader());
    } catch (ExecutionException e) {
      // If the operation failed during execution, expose the cause.
      throw (SpannerException) e.getCause();
    } catch (InterruptedException e) {
      // Throw when a thread is waiting, sleeping, or otherwise occupied,
      // and the thread is interrupted, either before or during the activity.
      throw SpannerExceptionFactory.propagateInterrupt(e);
    }
  }
}

<ph type="x-smartling-placeholder">

Node.js

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

如需向 Spanner 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为本地开发环境设置身份验证

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

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

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

// Gets a reference to a Cloud Spanner Database Admin Client object
const databaseAdminClient = spanner.getDatabaseAdminClient();

async function createDatabaseWithDefaultLeader() {
  // Create a new database with an extra statement which will alter the
  // database after creation to set the default leader.
  console.log(
    `Creating database ${databaseAdminClient.databasePath(
      projectId,
      instanceId,
      databaseId
    )}.`
  );
  const createSingersTableStatement = `
    CREATE TABLE Singers (
      SingerId   INT64 NOT NULL,
      FirstName  STRING(1024),
      LastName   STRING(1024),
      SingerInfo BYTES(MAX)
    ) PRIMARY KEY (SingerId)`;
  const createAlbumsStatement = `
    CREATE TABLE Albums (
      SingerId     INT64 NOT NULL,
      AlbumId      INT64 NOT NULL,
      AlbumTitle   STRING(MAX)
    ) PRIMARY KEY (SingerId, AlbumId),
      INTERLEAVE IN PARENT Singers ON DELETE CASCADE`;

  // Default leader is one of the possible values in the leaderOptions field of the
  // instance config of the instance where the database is created.
  const setDefaultLeaderStatement = `
    ALTER DATABASE \`${databaseId}\`
    SET OPTIONS (default_leader = '${defaultLeader}')`;

  const [operation] = await databaseAdminClient.createDatabase({
    createStatement: 'CREATE DATABASE `' + databaseId + '`',
    extraStatements: [
      createSingersTableStatement,
      createAlbumsStatement,
      setDefaultLeaderStatement,
    ],
    parent: databaseAdminClient.instancePath(projectId, instanceId),
  });

  console.log(`Waiting for creation of ${databaseId} to complete...`);
  await operation.promise();
  console.log(
    `Created database ${databaseId} with default leader ${defaultLeader}.`
  );
}
createDatabaseWithDefaultLeader();

<ph type="x-smartling-placeholder">

PHP

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

如需向 Spanner 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为本地开发环境设置身份验证

use Google\Cloud\Spanner\Admin\Database\V1\Client\DatabaseAdminClient;
use Google\Cloud\Spanner\Admin\Database\V1\CreateDatabaseRequest;

/**
 * Creates a database and tables for sample data.
 * Example:
 * ```
 * create_database($instanceId, $databaseId);
 * ```
 *
 * @param string $projectId The Google Cloud project ID.
 * @param string $instanceId The Spanner instance ID.
 * @param string $databaseId The Spanner database ID.
 */
function create_database(string $projectId, string $instanceId, string $databaseId): void
{
    $databaseAdminClient = new DatabaseAdminClient();
    $instance = $databaseAdminClient->instanceName($projectId, $instanceId);

    $operation = $databaseAdminClient->createDatabase(
        new CreateDatabaseRequest([
            'parent' => $instance,
            'create_statement' => sprintf('CREATE DATABASE `%s`', $databaseId),
            'extra_statements' => [
                'CREATE TABLE Singers (' .
                'SingerId     INT64 NOT NULL,' .
                'FirstName    STRING(1024),' .
                'LastName     STRING(1024),' .
                'SingerInfo   BYTES(MAX),' .
                'FullName     STRING(2048) AS' .
                '(ARRAY_TO_STRING([FirstName, LastName], " ")) STORED' .
                ') PRIMARY KEY (SingerId)',
                'CREATE TABLE Albums (' .
                    'SingerId     INT64 NOT NULL,' .
                    'AlbumId      INT64 NOT NULL,' .
                    'AlbumTitle   STRING(MAX)' .
                ') PRIMARY KEY (SingerId, AlbumId),' .
                'INTERLEAVE IN PARENT Singers ON DELETE CASCADE'
            ]
        ])
    );

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

    printf('Created database %s on instance %s' . PHP_EOL,
        $databaseId, $instanceId);
}

<ph type="x-smartling-placeholder">

Python

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

如需向 Spanner 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为本地开发环境设置身份验证

def create_database(instance_id, database_id):
    """Creates a database and tables for sample data."""
    from google.cloud.spanner_admin_database_v1.types import \
        spanner_database_admin

    spanner_client = spanner.Client()
    database_admin_api = spanner_client.database_admin_api

    request = spanner_database_admin.CreateDatabaseRequest(
        parent=database_admin_api.instance_path(spanner_client.project, instance_id),
        create_statement=f"CREATE DATABASE `{database_id}`",
        extra_statements=[
            """CREATE TABLE Singers (
            SingerId     INT64 NOT NULL,
            FirstName    STRING(1024),
            LastName     STRING(1024),
            SingerInfo   BYTES(MAX),
            FullName   STRING(2048) AS (
                ARRAY_TO_STRING([FirstName, LastName], " ")
            ) STORED
        ) PRIMARY KEY (SingerId)""",
            """CREATE TABLE Albums (
            SingerId     INT64 NOT NULL,
            AlbumId      INT64 NOT NULL,
            AlbumTitle   STRING(MAX)
        ) PRIMARY KEY (SingerId, AlbumId),
        INTERLEAVE IN PARENT Singers ON DELETE CASCADE""",
        ],
    )

    operation = database_admin_api.create_database(request=request)

    print("Waiting for operation to complete...")
    database = operation.result(OPERATION_TIMEOUT_SECONDS)

    print(
        "Created database {} on instance {}".format(
            database.name,
            database_admin_api.instance_path(spanner_client.project, instance_id),
        )
    )

<ph type="x-smartling-placeholder">

Ruby

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

如需向 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

job = database_admin_client.create_database parent: instance_path,
                                            create_statement: "CREATE DATABASE `#{database_id}`",
                                            extra_statements: [
                                              "CREATE TABLE Singers (
      SingerId     INT64 NOT NULL,
      FirstName    STRING(1024),
      LastName     STRING(1024),
      SingerInfo   BYTES(MAX)
    ) PRIMARY KEY (SingerId)",

                                              "CREATE TABLE Albums (
      SingerId     INT64 NOT NULL,
      AlbumId      INT64 NOT NULL,
      AlbumTitle   STRING(MAX)
    ) PRIMARY KEY (SingerId, AlbumId),
    INTERLEAVE IN PARENT Singers ON DELETE CASCADE"
                                            ]

puts "Waiting for create database operation to complete"

job.wait_until_done!

puts "Created database #{database_id} on instance #{instance_id}"

更新数据库架构或选项

您可以使用 DDL 语句更新数据库架构和选项。

例如,如需向表中添加列,请使用以下 DDL 语句:

GoogleSQL

ALTER TABLE Songwriters ADD COLUMN Publisher STRING(10);

PostgreSQL

ALTER TABLE Songwriters ADD COLUMN Publisher VARCHAR(10);

如需更新查询优化器版本,请使用以下 DDL 语句:

GoogleSQL

ALTER DATABASE Music SET OPTIONS(optimizer_version=null);

PostgreSQL

ALTER DATABASE DB-NAME SET spanner.optimizer_version TO DEFAULT;

如需详细了解支持的选项,请参阅 ALTER DATABASE DDL 适用于 GoogleSQLPostgreSQL

如需了解架构更新,请参阅 进行架构更新

控制台

  1. 前往 Google Cloud 控制台中的实例页面。

    实例

  2. 选择包含要更改的数据库的实例。

  3. 选择数据库。

  4. 点击 Spanner Studio

  5. 点击 新标签页,或使用空白 编辑器标签页。然后,输入要应用的 DDL 语句。

  6. 点击运行以应用更新。如果 DDL 中存在错误 Google Cloud 控制台返回错误,且数据库 。

gcloud

如需使用 gcloud 命令行工具更改数据库,请使用 gcloud spanner databases ddl update

gcloud spanner databases ddl update \
(DATABASE : --instance=INSTANCE) \
[--async] \
[--ddl=DDL] \
[--ddl-file=DDL_FILE] \

请参阅 gcloud 参考文档 详细了解可用选项

使用 --ddl 标志或 --ddl-file 标志。如果指定了 DDL 文件,则会忽略 --ddl 标志。

参阅 ALTER DATABASE DDL 参考文档 对于 GoogleSQLPostgreSQL:需要包含的 DDL 语句。

DDL

参阅 ALTER DATABASE DDL 参考文档 对于 GoogleSQLPostgreSQL

检查架构更新操作的进度

控制台

  1. 在 Spanner 导航菜单中,选择操作标签页。通过 操作页面显示了当前正在运行的操作的列表。

  2. 在列表中找到架构操作。如果它仍在运行 结束时间列中的一个长条显示了符合以下条件的操作所占的百分比: 完成,如下图所示:

显示 98% 的进度条的屏幕截图

gcloud

使用gcloud spanner operations describe 来检查操作进度。

  1. 获取操作 ID:

    gcloud spanner operations list --instance=INSTANCE-NAME \
    --database=DATABASE-NAME --type=DATABASE_UPDATE_DDL
    

    替换以下内容:

    • INSTANCE-NAME 替换为 Spanner 实例 名称。
    • DATABASE-NAME 替换为数据库的名称。
  2. 运行 gcloud spanner operations describe

    gcloud spanner operations describe OPERATION_ID\
    --instance=INSTANCE-NAME \
    --database=DATABASE-NAME
    

    替换以下内容:

    • OPERATION-ID:您要执行的操作的 ID 检查。
    • INSTANCE-NAME:Spanner 实例名称。
    • DATABASE-NAME:Spanner 数据库名称。

    输出中的 progress 部分显示了操作所占的百分比 这样就完成了输出类似于以下内容:

    done: true
    metadata:
    ...
      progress:
      - endTime: '2022-03-01T00:28:06.691403Z'
        progressPercent: 100
        startTime: '2022-03-01T00:28:04.221401Z'
      - endTime: '2022-03-01T00:28:17.624588Z'
        startTime: '2022-03-01T00:28:06.691403Z'
        progressPercent: 100
    ...
    

REST v1

  1. 获取操作 ID:

    gcloud spanner operations list --instance=INSTANCE-NAME \
    --database=DATABASE-NAME --type=DATABASE_UPDATE_DDL
    

    替换以下内容:

    • INSTANCE-NAME 替换为 Spanner 实例 名称。
    • DATABASE-NAME 替换为数据库名称。
  2. 检查操作的进度。

    在使用任何请求数据之前,请先进行以下替换:

    • PROJECT-ID:项目 ID。
    • INSTANCE-ID:实例 ID。
    • DATABASE-ID:数据库 ID。
    • OPERATION-ID:操作 ID。

    HTTP 方法和网址:

    GET https://spanner.googleapis.com/v1/projects/PROJECT-ID/instances/INSTANCE-ID/databases/DATABASE-ID/operations/OPERATION-ID

    如需发送您的请求,请展开以下选项之一:

    您应该收到类似以下内容的 JSON 响应:

    {
    ...
        "progress": [
          {
            "progressPercent": 100,
            "startTime": "2023-05-27T00:52:27.366688Z",
            "endTime": "2023-05-27T00:52:30.184845Z"
          },
          {
            "progressPercent": 100,
            "startTime": "2023-05-27T00:52:30.184845Z",
            "endTime": "2023-05-27T00:52:40.750959Z"
          }
        ],
    ...
      "done": true,
      "response": {
        "@type": "type.googleapis.com/google.protobuf.Empty"
      }
    }
    
    

如果操作耗时过长,您可以取消该操作。如需了解详情,请参阅 取消长时间运行的数据库操作

删除数据库

删除数据库将会永久移除该数据库及其所有数据。数据库 删除操作无法撤消。如果执行数据库删除保护 则无法删除该数据库,除非您停用其 删除保护

删除数据库时,现有备份不会删除。有关 相关信息,请参阅备份和恢复

控制台

  1. 前往 Google Cloud 控制台中的实例页面。

    实例

  2. 选择包含要删除的数据库的实例。

  3. 选择数据库。

  4. 点击删除数据库。系统会显示确认消息。

  5. 输入数据库名称,然后点击删除

gcloud

如需使用 gcloud 命令行工具删除数据库,请使用 gcloud spanner databases delete

gcloud spanner databases delete \
  (DATABASE : --instance=INSTANCE)

以下选项为必需:

DATABASE
数据库的 ID 或数据库的完全限定标识符。如果 提供的是完全限定的标识符,即 --instance 标志应省略。
--instance=INSTANCE
数据库的 Spanner 实例。

有关详情,请参阅 gcloud 参考文档

DDL

DDL 不支持数据库删除语法。

后续步骤