使用時間點復原 (PITR)

本頁說明如何使用時間點復原 (PITR) 功能,保留及復原 Datastore 模式的 Firestore 資料。

如要瞭解 PITR 概念,請參閱「時間點復原」。

權限

如要取得管理 PITR 設定所需的權限,請要求管理員授予您要啟用 PITR 設定的專案「Cloud Datastore 擁有者 」(roles/datastore.owner) IAM 角色。如要進一步瞭解如何授予角色,請參閱「管理專案、資料夾和組織的存取權」。

這個預先定義的角色具備管理 PITR 設定所需的權限。如要查看確切的必要權限,請展開「Required permissions」(必要權限) 部分:

所需權限

如要管理 PITR 設定,您必須具備下列權限:

  • 如要在建立資料庫時啟用 PITR,請執行下列步驟: datastore.databases.create
  • 如要更新現有資料庫的 PITR 設定,請按照下列步驟操作: datastore.databases.update,datastore.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 後,您無法立即開始讀取七天前的資料。
  • 如要在建立資料庫時啟用 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 控制台的「Databases」(資料庫) 頁面。

    前往「資料庫」

  2. 從資料庫清單中選取所需資料庫。

  3. 在導覽選單中,按一下「Disaster Recovery」(災難復原)

  4. 按一下「編輯」即可編輯設定。

  5. 勾選「Enable point-in-time recovery」(啟用時間點復原) 核取方塊,然後按一下「Save」(儲存)

啟用 PITR 會產生儲存費用。詳情請參閱定價

如要停用 PITR,請在 Google Cloud 控制台的「Disaster Recovery」(災害復原) 頁面中,取消勾選「Enable point-in-time recovery」(啟用時間點復原) 核取方塊。

gcloud

使用 gcloud firestore databases create 指令建立資料庫時,啟用時間點復原功能,如下所示:

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 控制台的「Databases」(資料庫) 頁面。

    前往「資料庫」

  2. 從資料庫清單中選取所需資料庫。

  3. 在導覽選單中,按一下「Disaster Recovery」(災難復原)

  4. 在「設定」部分,記下「保留期限」和「最早版本時間」

    • 保留期限:Datastore 模式保留資料庫所有資料版本的期限。如果停用時間點復原功能,保留期限為一小時;如果啟用時間點復原功能,保留期限為七天。
    • 最早版本時間:時間點復原 (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,值可以是一小時;如果啟用 PITR,值可以是七天。

讀取 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 中,使用 readTime 方法執行 PITR 讀取作業,或使用 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 加密。

  • 時間戳記的精細度為一分鐘,且指定過去的時間點,位於 PITR 視窗定義的期間內:

    • 如果資料庫已啟用 PITR,您可以選取過去 7 天內的任何時間點 (如果啟用 PITR 的時間未滿 7 天,則為啟用 PITR 之後的任何時間點)。
    • 如果未啟用 PITR,您可以選取過去一小時內的任一分鐘。
    • 你可以查看資料庫說明中可選取的最早時間戳記。

控制台

  1. 前往 Google Cloud 控制台的「Databases」(資料庫) 頁面。

    前往「資料庫」

  2. 在要複製的資料庫表格列中,按一下「查看更多」。按一下「Clone」(複製)。系統會顯示「建立副本」對話方塊。

  3. 在「Create a clone」(建立副本) 對話方塊中,提供資料庫副本的參數:

    1. 在「為本機副本提供 ID」欄位中,輸入新複製資料庫的資料庫 ID。這個資料庫 ID 不得與現有資料庫建立關聯。

    2. 在「Clone from」(從以下時間點複製) 欄位中,選取要用於複製的時間點。 所選時間對應至 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_TIMESTAMPPITR 時間戳記,採用 RFC 3339 格式,精確度為分鐘。例如: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。您可以匯出時間戳記為過去七天內整分鐘的時間點復原資料,但不得早於 earliestVersionTime。如果指定時間戳記的資料已不存在,匯出作業就會失敗。

PITR 匯出作業支援所有篩選器,包括匯出所有實體,以及匯出特定種類或命名空間。

  1. 匯出資料庫,並將 snapshot-time 參數指定為所需復原時間戳記。

    gcloud

    執行下列指令,將資料庫匯出至 bucket。

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

    其中

    • BUCKET_NAME_PATH - 有效的 Cloud Storage bucket,以及儲存匯出檔案的選用路徑前置字串。
    • 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
    • 請確認指定的時間戳記是過去 7 天內的整分時間戳記,但不得早於 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