使用时间点恢复 (PITR)

本页介绍如何使用时间点恢复 (PITR) 来保留和恢复 Datastore 模式 Firestore 中的数据。

如需了解 PITR 概念,请参阅时间点恢复

权限

如需获取管理 PITR 设置所需的权限,请让管理员向您授予您想要启用 PITR 设置的项目的 Cloud Datastore Owner (roles/datastore.owner) IAM 角色。如需详细了解如何授予角色,请参阅管理对项目、文件夹和组织的访问权限

此预定义角色包含管理 PITR 设置所需的权限。如需查看所需的确切权限,请展开所需权限部分:

所需权限

您需要具备以下权限才能管理 PITR 设置:

  • 如需在创建数据库时启用 PITR: datastore.databases.create
  • 如需更新现有数据库上的 PITR 设置: datastore.databases.updatedatastore.databases.list
  • 如需从 PITR 数据进行读取: datastore.databases.getdatastore.entities.getdatastore.entities.listdatastore.namespaces.getdatastore.namespaces.listdatastore.statistics.getdatastore.statistics.list
  • 如需导出 PITR 数据,请执行以下操作: datastore.databases.export
  • 如需导入 PITR 数据: datastore.databases.import

您也可以使用自定义角色或其他预定义角色来获取这些权限。

准备工作

在开始使用 PITR 之前,请注意以下几点:

  • 启用 PITR 后,您无法立即开始读取过去 7 天内的数据。
  • 如果您要在创建数据库时启用 PITR,必须使用 gcloud firestore databases create 命令。使用 Google Cloud 控制台创建数据库时不支持启用 PITR。
  • 启用 PITR 后,Datastore 模式会立即开始保留版本。
  • 停用 PITR 后,您将无法在 PITR 窗口中读取 PITR 数据。
  • 如果您在停用 PITR 后立即将其重启,则过去的 PITR 数据将不再可用。系统将在 PITR 失效日期之后删除停用 PITR 之前创建的任何 PITR 数据。
  • 如果您在过去一小时内不小心删除了数据并停用了 PITR,则可以在删除后的一小时内启用 PITR,从而恢复数据。
  • 对已过期的 PITR 数据执行的任何读取操作都会失败。

启用 PITR

在使用 PITR 之前,请为您的 Google Cloud项目启用结算功能。只有启用了结算功能的 Google Cloud 项目才能使用 PITR 功能。

如需为数据库启用 PITR,请执行以下操作:

控制台

  1. 在 Google Cloud 控制台中,前往数据库页面。

    前往“数据库”

  2. 从数据库列表中选择所需的数据库。

  3. 在导航菜单中,点击灾难恢复

  4. 点击修改以修改设置。

  5. 选中启用时间点恢复复选框,然后点击保存

启用 PITR 会产生存储费用。如需了解详情,请参阅价格

如需停用 PITR,请在 Google Cloud 控制台的“灾难恢复”页面中取消选中启用时间点恢复复选框。

gcloud

可以使用 gcloud firestore databases create 命令在创建数据库期间启用 PITR,如下所示:

gcloud firestore databases create\
  --location=LOCATION\
  [--database=DATABASE_ID; default="(default)"]\
  [--type=TYPE; default="firestore-native"]\
  --enable-pitr

替换各值,如下所示:

  • LOCATION - 要在其中创建数据库的位置。
  • DATABASE_ID - 设置为数据库 ID 或(使用默认值)。
  • TYPE - 设置为 datastore-mode。

您可以使用 [gcloud firestore databases update][update] 命令停用 PITR,如下所示:

gcloud firestore databases update\
  [--database=DATABASE_ID; default="(default)"]\
  --no-enable-pitr

替换各值,如下所示:

  • DATABASE_ID - 设置为数据库 ID 或(使用默认值)。

获取保留期限和最早版本时间

控制台

  1. 在 Google Cloud 控制台中,前往数据库页面。

    前往“数据库”

  2. 从数据库列表中选择所需的数据库。

  3. 在导航菜单中,点击灾难恢复

  4. 设置部分中,注意保留期限最早版本时间

    • 保留期限:Datastore 模式为数据库保留所有数据版本的时长。如果停用了 PITR,该值为 1 小时;如果启用了 PITR,该值为 7 天。
    • 最早版本时间:可在 PITR 窗口中读取旧版数据的最早时间戳。该值会由 Datastore 模式不断更新,并且会在查询时过时。如果您使用该值恢复数据,请确保计算从发出查询到查询恢复那一刻这段时间。
    • 时间点恢复:如果启用了 PITR,则显示 Enabled。如果停用了 PITR,您会看到 Disabled

gcloud

运行 gcloud firestore databases describe 命令,如下所示:

gcloud firestore databases describe --database=DATABASE_ID

DATABASE_ID 替换为数据库 ID 或 (default)

输出如下:

    appEngineIntegrationMode: ENABLED
    concurrencyMode: PESSIMISTIC
    createTime: '2021-03-24T17:02:35.234Z'
    deleteProtectionState: DELETE_PROTECTION_DISABLED
    earliestVersionTime: '2023-06-12T16:17:25.222474Z'
    etag: IIDayqOevv8CMNTvyNK4uv8C
    keyPrefix: s
    locationId: nam5
    name: projects/PROJECT_ID/databases/(default)
    pointInTimeRecoveryEnablement: POINT_IN_TIME_RECOVERY_DISABLED
    type: DATASTORE_MODE
    uid: 5230c382-dcd2-468f-8cb3-2a1acfde2b32
    updateTime: '2021-11-17T17:48:22.171180Z'
    versionRetentionPeriod: 3600s

其中

  • earliestVersionTime - 最早存储的 PITR 数据的时间戳。
  • pointInTimeRecoveryEnablement:如果启用了 PITR,则显示 POINT_IN_TIME_RECOVERY_ENABLED。如果停用了 PITR,您会看到 POINT_IN_TIME_RECOVERY_DISABLED,或者 pointInTimeRecoveryEnablement 字段可能不会显示。
  • versionRetentionPeriod - 保留 PITR 数据的时间段(以毫秒为单位)。如果停用 PITR,该值可能是 1 小时;如果启用了 PITR,则可能是 7 天。

读取 PITR 数据

您可以使用客户端库、REST API 方法或 FirestoreIO Apache Beam 连接器读取 PITR 数据。

客户端库

Java

您必须使用 ReadOption 类中的 readTime 方法来读取 PITR 数据。您无法使用 ReadOnly 事务执行读取操作。如需了解详情,请参阅 [ReadOption][readoption] 示例代码。

  Datastore datastore = ...
  Timestamp timestamp = ...

  // lookup
  Key key = ...
  Entity entity = datastore.get(key, ReadOption.readTime(timestamp));

  // runQuery
  Query<Entity> query = ...
  QueryResults<Entity> queryResult = datastore.run(query, ReadOption.readTime(timestamp));

  // runAggregationQuery
  AggregationQuery countAggregationQuery = ...
  Long count = getOnlyElement(datastore.runAggregation(countAggregationQuery, ReadOption.readTime(timestamp))).get("total_count");

如需查看 readTime 示例的完整列表,请参阅 [GitHub 代码库][GitHub-java]。

Python

在 Datastore 模式 Python SDK 中使用 PITR 读取,方法是使用 readTime 方法或使用 ReadOnly 事务与 readTime 来执行读取。

  from datetime import datetime, timezone

  read_time = datetime.now(tz=timezone.utc)

  key = 
  # read without PITR read time
  entity = client.get(key)

  # read with PITR read time
  entity = client.get(key, read_time=read_time)

  # PITR read using read_only transaction
  with client.transaction(read_only=True, read_time=read_time):
      entity = client.get(key)

  query = client.query
  # run query without PITR read time
  iterator = query.fetch()

  # run query with PITR read time
  iterator = query.fetch(read_time=read_time)

  # PITR read query using read_only transaction
  with client.transaction(read_only=True, read_time=read_time):
      iterator = query.fetch()

如需查看 readTime 示例的完整列表,请参阅 [GitHub][GitHub-python] 代码库。

REST API

Datastore 模式 V1 读取方法支持 PITR 读取,这些方法包括 [lookup][lookup]、[runQuery][runQuery] 和 [runAggregationQuery][runAggregationQuery]。

如需使用 REST 方法执行读取操作,请尝试以下方法之一:

  1. 在读取方法请求中,将 readTime 值作为支持的 PITR 时间戳传递给 readOptions 方法。PITR 时间戳可以是过去一小时内的微秒精度时间戳,也可以是过去一小时之前的完整一分钟时间戳,但不得早于 earliestVersionTime

  2. readTime 参数与 BeginTransaction 方法一起使用,作为 [ReadOnly 事务][readonly] 的一部分以用于多次 PITR 读取。

Apache Beam

使用 Datastore 模式 IO Apache Beam 连接器可以通过 Dataflow 大规模读取或写入 Datastore 模式数据库中的实体。

在 [DatastoreV1.Read][datastore-read] 对象上指定 withReadTime(Instant readTime) 方法。使用 DatastoreV1.Read 对象的所有后续读取操作都从同一 readTime 读取。

Java

以下代码展示了如何使用 withReadTime 方法进行 PITR 读取。

  com.google.datastore.v1.Query query = ...
    Instant readTime = Instant.ofEpochSecond(1684098540L);

    DatastoreV1.Read read =
            DatastoreIO.v1()
                .read()
                .withProjectId(project)
                .withQuery(query)
                .withNamespace(namespace)
                .withReadTime(readTime);

    PCollection<Entity> entities = pipeline.apply(read);
    ...

如需查看 withReadTime 示例的完整列表,请参阅 [GitHub][GitHub] 代码库。

从数据库克隆

您可以将现有数据库在选定时间点的数据克隆到新的数据库中:

  • 克隆的数据库是一个新数据库,将在源数据库所在的同一位置创建。

    为了创建克隆,Firestore 使用源数据库的时间点恢复 (PITR) 数据。克隆的数据库包含所有数据和索引。

  • 默认情况下,克隆的数据库将采用与源数据库相同的加密方式(Google 默认加密或 CMEK 加密)。您可以指定其他加密类型,也可以使用其他密钥进行 CMEK 加密。

  • 时间戳的粒度为 1 分钟,它指定了过去的一个时间点,该时间点必须在 PITR 时间窗口定义的时段内:

    • 如果数据库已启用 PITR,您可以选择过去 7 天内的任意一分钟(如果 PITR 启用时间不足 7 天,则可选择启用以来的任意一分钟)。
    • 如果未启用 PITR,您可以选择过去一小时内的任意一分钟。
    • 您可以在数据库的说明中查看可选择的最早时间戳。

控制台

  1. 在 Google Cloud 控制台中,前往数据库页面。

    前往“数据库”

  2. 在要克隆的数据库对应的表行中,点击 查看更多。点击克隆。随即会出现创建克隆对话框。

  3. 创建克隆对话框中,提供克隆数据库时要使用的参数:

    1. 为克隆分配一个 ID 字段中,输入新克隆数据库的数据库 ID。此数据库 ID 不能与现有数据库关联。

    2. 从以下时间点开始克隆字段中,选择要用于克隆的时间点。所选时间对应于以分钟为粒度的 PITR 时间戳。

  4. 点击创建克隆

gcloud

使用 gcloud firestore databases clone 命令克隆数据库:

gcloud firestore databases clone \
--source-database='SOURCE_DATABASE' \
--snapshot-time='PITR_TIMESTAMP' \
--destination-database='DESTINATION_DATABASE_ID'

替换以下内容:

  • SOURCE_DATABASE:要克隆的现有数据库的名称。该名称使用 projects/PROJECT_ID/databases/SOURCE_DATABASE_ID 格式。

  • PITR_TIMESTAMP:采用 RFC 3339 格式PITR 时间戳,精确到分钟。例如:2025-06-01T10:20:00.00Z2025-06-01T10:30:00.00-07:00

  • DESTINATION_DATABASE_ID:新克隆数据库的数据库 ID。此数据库 ID 必须与现有数据库无关联。

示例:

gcloud firestore databases clone \
--source-database='projects/example-project/databases/(default)' \
--snapshot-time='2025-06-01T10:20:00.00Z' \
--destination-database='example-dest-db'

更改克隆数据库的加密配置

默认情况下,克隆的数据库将具有与源数据库相同的加密配置。如需更改加密配置,请使用 --encryption-type 参数:

  • (默认)use-source-encryption:使用与源数据库相同的加密配置。
  • google-default-encryption:使用 Google 的默认加密方式。
  • customer-managed-encryption:使用 CMEK 加密。在 --kms-key-name 参数中指定密钥 ID

以下示例展示了如何为克隆的数据库配置 CMEK 加密:

gcloud firestore databases clone \
--source-database='projects/example-project/databases/(default)' \
--snapshot-time='2025-06-01T10:20:00.00Z' \
--destination-database='example-dest-db' \
--encryption-type='customer-managed-encryption' \
--kms-key-name='projects/example-project/locations/us-central1/keyRings/example-key-ring/cryptoKeys/example-key'

从 PITR 数据导出和导入

您可以使用 [gcloud firestore export][sdk] 命令将数据库从 PITR 数据导出到 Cloud Storage。您可以导出 PITR 数据,其中时间戳为过去七天内的整分钟时间戳,但不早于 earliestVersionTime。如果指定的时间戳已不存在数据,导出操作将失败。

PITR 导出操作支持所有过滤条件,包括导出所有实体以及导出特定种类或命名空间的实体。

  1. 导出数据库,将 snapshot-time 参数指定为所需恢复时间戳。

    gcloud

    运行以下命令,将数据库导出到存储桶。

    gcloud firestore export gs://[BUCKET_NAME_PATH] \
        --snapshot-time=[PITR_TIMESTAMP] \
        --collection-ids=[COLLECTION_IDS] \
        --namespace-ids=[NAMESPACE_IDS]
    

    其中:

    • BUCKET_NAME_PATH - 有效的 Cloud Storage 存储桶(包含可选路径前缀),用于存储导出文件。
    • PITR_TIMESTAMP - 分钟粒度的 PITR 时间戳,例如 2023-05-26T10:20:00.00Z2023-10-19T10:30:00.00-07:00
    • COLLECTION_IDS - 集合 ID 或集合组 ID 的列表,例如 'specific collection group1','specific collection group2'
    • NAMESPACE_IDS - 命名空间 ID 的列表,例如 'customer''orders'

    系统还支持使用实体过滤条件导出种类和/或命名空间的特定子集

    在导出 PITR 数据之前,请注意以下几点:

    • RFC 3339 格式指定时间戳。例如 2023-05-26T10:20:00.00Z2023-10-19T10:30:00.00-07:00
    • 请确保您指定的时间戳是过去七天内的整分钟时间戳,但不早于 earliestVersionTime。如果指定时间戳下数据不再存在,您将收到错误消息。时间戳必须是整分钟,即使指定的时间在过去一小时内也是如此。
    • 您无需为失败的 PITR 导出付费。
  2. 导入到数据库。

    按照 [导入所有实体][import-export]中的步骤导入您导出的数据库。如果数据库中已有任何实体,这类实体将会被覆盖。系统还支持 [使用实体过滤条件导入种类和/或命名空间的特定子集][import-kind]。

[GitHub]:https://github.com/apache/beam/blob/master/sdks/java/io/google-cloud-platform/src/test/java/org/apache/beam/sdk/io/gcp/datastore/V1ReadIT.java [GitHub-java]:https://github.com/googleapis/java-datastore/blob/main/google-cloud-datastore/src/test/java/com/google/cloud/datastore/it/ITDatastoreTest.java [GitHub-python]:https://github.com/googleapis/python-datastore/blob/main/tests/system/test_read_consistency.py [lookup]:/datastore/docs/reference/data/rest/v1/projects/lookup [runQuery]:/datastore/docs/reference/data/rest/v1/projects/runQuery [runAggregationQuery]:/datastore/docs/reference/data/rest/v1/projects/runAggregationQuery [readonly]:/java/docs/reference/google-cloud-datastore/latest/com.google.datastore.v1#transactionoptions.readonly [import-export]:/datastore/docs/export-import-entities#importing_all_entities [update]:https://cloud.google.com/sdk/gcloud/reference/firestore/databases/update [datastore-read]:https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/io/gcp/datastore/DatastoreV1.Read.html [readoption]:https://github.com/googleapis/java-datastore/blob/main/google-cloud-datastore/src/main/java/com/google/cloud/datastore/ReadOption.java [import-kind]:/datastore/docs/export-import-entities#importing_specific_kinds_or_namespaces [sdk]:/sdk/gcloud/reference/firestore/export