建立及管理資料庫

本頁說明如何管理 Spanner 資料庫,包括如何建立資料庫、修改資料庫選項,以及刪除資料庫。本頁面提供 GoogleSQL 方言資料庫和 PostgreSQL 方言資料庫的相關資訊。如要瞭解如何更新資料庫結構定義,請參閱「更新結構定義」。

如要練習建立資料庫並載入範例資料,請參閱 Spanner 資料庫程式碼研究室

建立資料庫

下列範例說明如何在現有執行個體中建立資料庫。

如果是 GoogleSQL 方言資料庫,您可以在建立資料庫時或建立後定義資料庫結構定義。如果是 PostgreSQL 方言資料庫,您必須在建立後定義結構定義。

結構定義是使用資料庫定義語言定義,相關文件請參閱 GoogleSQLPostgreSQL。如要進一步瞭解如何建立及更新結構定義,請參閱下列連結:

建立資料庫後,您可以啟用資料庫防刪除功能,保護對應用程式和服務而言重要的資料庫。詳情請參閱「防止意外刪除資料庫」。

Google Cloud 控制台

  1. 前往 Google Cloud 控制台的「Spanner Instances」(Spanner 執行個體) 頁面。

    前往 Spanner 執行個體

  2. 選取要建立資料庫的執行個體。

  3. 按一下 [Create database] (建立資料庫)。

  4. 輸入下列值:

    • 顯示於 Google Cloud 控制台中的資料庫名稱
    • 這個資料庫要使用的方言
    • 如果是 GoogleSQL 方言資料庫,您可以選擇提供一組定義結構定義的 DDL 陳述式。使用 DDL 範本預先填入常見元素。如果 DDL 陳述式有錯誤,當您嘗試建立資料庫時, Google Cloud 控制台會傳回錯誤。
    • (選用) 選取要用於這個資料庫的客戶自行管理加密金鑰
  5. 按一下「建立」即可建立資料庫。

gcloud

使用 gcloud spanner databases create 指令。

```sh
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 或完整 ID。如果指定完整 ID,則可以省略 --instance 標記。
--instance=INSTANCE
資料庫的 Spanner 執行個體。

以下是選用選項:

--async
立即傳回,不必等待進行中的作業完成。
--database-dialect=DATABASE_DIALECT
Spanner 資料庫的 SQL 方言。必須是下列之一:POSTGRESQLGOOGLE_STANDARD_SQL
--ddl=DDL
以半形分號分隔的 DDL (資料定義語言) 陳述式,可在新建立的資料庫中執行。如果任何陳述式發生錯誤,系統就不會建立資料庫。如果已設定 --ddl_file,系統會忽略這個旗標。PostgreSQL 方言資料庫不支援這項功能。
--ddl-file=DDL_FILE
檔案路徑,其中包含以半形分號分隔的 DDL (資料定義語言) 陳述式,可在新建立的資料庫中執行。如果任何陳述式發生錯誤,系統就不會建立資料庫。如果設定 --ddl_file,系統就會忽略 --ddl。PostgreSQL 方言資料庫不支援這項功能。

如要指定建立資料庫時使用的 Cloud Key Management Service 金鑰,請加入下列選項:

--kms-key=KMS_KEY
金鑰的 ID 或完整 ID。

如果指定這個群組中的任何其他引數,就必須設定這個旗標。如果提供完整 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 進行驗證,請設定應用程式預設憑證。 詳情請參閱「為本機開發環境設定驗證」。

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 進行驗證,請設定應用程式預設憑證。 詳情請參閱「為本機開發環境設定驗證」。

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 進行驗證,請設定應用程式預設憑證。 詳情請參閱「為本機開發環境設定驗證」。


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);
    }
  }
}

Node.js

如要瞭解如何安裝及使用 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();

PHP

如要瞭解如何安裝及使用 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);
}

Python

如要瞭解如何安裝及使用 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),
        )
    )

Ruby

如要瞭解如何安裝及使用 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 GoogleSQLPostgreSQL 的 DDL 參考資料。

如要瞭解如何更新結構定義,請參閱更新結構定義

Google Cloud 控制台

  1. 前往 Google Cloud 控制台的「Spanner Instances」(Spanner 執行個體) 頁面。

    前往 Spanner 執行個體

  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 旗標。

PostgreSQL

DDL

詳情請參閱 ALTER DATABASE GoogleSQL GoogleSQLPostgreSQL 的 DDL 參考資料。

查看結構定義更新作業的進度

Google Cloud 控制台

  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"
      }
    }
    
    

如果作業時間過長,可以取消作業。詳情請參閱取消長時間執行的資料庫作業

刪除資料庫

在您刪除資料庫之後,系統將永久移除該資料庫及其所有資料。資料庫刪除後即無法復原。如果資料庫已啟用防刪除功能,您必須停用該功能,才能刪除資料庫。

刪除資料庫時,系統不會刪除現有備份。詳情請參閱「備份及還原」。

Google Cloud 控制台

  1. 前往 Google Cloud 控制台的「Spanner Instances」(Spanner 執行個體) 頁面。

    前往 Spanner 執行個體

  2. 選取包含要刪除資料庫的執行個體。

  3. 選取資料庫。

  4. 按一下「刪除資料庫」。系統會顯示確認訊息。

  5. 輸入資料庫名稱,然後按一下「Delete」

gcloud

如要使用 gcloud 指令列工具刪除資料庫,請使用 gcloud spanner databases delete

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

以下是必要選項:

DATABASE
資料庫的 ID 或完整 ID。如果提供完整識別碼,則應省略 --instance 標記。
--instance=INSTANCE
資料庫的 Spanner 執行個體。

詳情請參閱gcloud參考資料

DDL

DDL 不支援資料庫刪除語法。

後續步驟