导出和导入实体

本页介绍如何使用托管式导出和导入服务来导出和导入 Datastore 模式 Firestore 实体。您可以通过 Cloud Console、gcloud 命令行工具及 Datastore Admin API(RESTRPC)使用托管式导出和导入服务。

利用托管式导出和导入服务,您可以恢复意外删除的数据,可以导出数据进行离线处理。您可以导出所有实体,或仅导出特定种类的实体。同样地,您可以从某个导出中导入所有数据,或仅导入特定种类的数据。使用托管式导出和导入服务时,请注意以下事项:

  • 导出服务使用最终一致的读取。您不能假定导出发生在单一时间点上。导出可能包括导出开始后写入的实体,并排除导出开始前写入的实体。

  • 导出不包含任何索引。在您导入数据时,将使用数据库当前的索引定义自动重建所需索引。每个实体的属性值索引设置会被导出,并在导入时得以保持。

  • 导入不会向实体分配新 ID。导入使用导出时存在的 ID,并覆盖具有相同 ID 的任何现有实体。在导入过程中,正在导入的实体的 ID 将被预留。如果在导入运行过程中启用了写入,此功能可防止与新实体发生 ID 冲突。

  • 如果数据库中的某个实体未受到导入服务的影响,则在导入完成后,该实体将保留在数据库中。

  • 从一个 Datastore 模式数据库导出的数据可导入另一个 Datastore 模式数据库中,甚至可以导入到属于其他项目的此类数据库中。

  • 托管式导出和导入服务将并发导出和导入操作数限制为 50,并且对于一个项目每分钟最多允许 20 条导出和导入请求。

  • 托管导出的输出使用 LevelDB 日志格式

  • 如需只导入实体的子集,或者如需将数据导入 BigQuery,您必须在导出中指定实体过滤条件

准备工作

在使用托管式导出和导入服务之前,您必须完成以下任务。

  1. 为 Google Cloud 项目启用结算功能。 只有启用了结算功能的 Google Cloud 项目才能使用导出和导入功能。

  2. Datastore 模式 Firestore 数据库所在的位置创建 Cloud Storage 存储分区。您不能使用“请求者付款”存储分区执行导出和导入操作。

  3. 如果要导出数据,请为您的用户帐号分配一个授予 datastore.databases.export 权限的 IAM 角色;如果要导入数据,请为您的用户帐号分配一个授予 datastore.databases.import 权限的 IAM 角色。例如,Datastore Import Export Admin 角色可同时授予这两种权限。

  4. 如果 Cloud Storage 存储分区位于其他项目中,则为您项目的默认服务帐号授予对该存储分区的访问权限

为您的项目设置 gcloud

如果您计划使用 gcloud 开始执行您的导入和导出操作,请设置 gcloud 并通过以下方式之一关联到您的项目:

开始执行托管式导出和导入操作

本部分介绍如何开始执行托管式导出或导入操作。

导出所有实体

控制台

  1. 转到 Google Cloud Console 中的 Datastore 实体导出页面。

    转到“Datastore 导出”页面

  2. 命名空间字段设置为 All Namespaces,并将种类字段设置为 All Kinds

  3. 目标下,输入您的 Cloud Storage 存储分区的名称。

  4. 点击导出

控制台会打开实体并报告您的托管式导出请求是成功还是失败。

控制台还会显示查看状态按钮。 点击此按钮可打开 Cloud Shell 终端,该终端预先填充了查看操作状态所需的 gcloud 命令。

只要您想查看操作的状态,就可以运行此命令。

gcloud

使用 gcloud datastore export 命令导出数据库中的所有实体。

 gcloud datastore export gs://bucket-name --async

其中 bucket-name 是您的 Cloud Storage 存储分区的名称和可选前缀,例如 bucket-name/firestore-exports/export-name。您无法为其他导出操作重复使用相同的前缀。如果您不提供文件前缀,托管式导出服务会根据当前时间戳创建一个。

使用 --async 标志阻止 gcloud 等待操作完成。如果您省略 --async 标志,则可以输入 Ctrl+c 以停止等待某一操作。这不会取消该操作。

rest

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

  • project-id:您的项目 ID
  • bucket-name:Cloud Storage 存储分区的名称

HTTP 方法和网址:

POST https://datastore.googleapis.com/v1/projects/project-id:export

请求 JSON 正文:

    {
      "outputUrlPrefix": "gs://bucket-name",
    }
    

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

您应会收到如下所示的 JSON 响应:

    {
      "name": "projects/project-id/operations/operation-id",
      "metadata": {
        "@type": "type.googleapis.com/google.datastore.admin.v1.ExportEntitiesMetadata",
        "common": {
          "startTime": "2019-09-18T18:42:26.591949Z",
          "operationType": "EXPORT_ENTITIES",
          "state": "PROCESSING"
        },
        "entityFilter": {},
        "outputUrlPrefix": "gs://bucket-name/2019-09-18T18:42:26_85726"
      }
    }
    
该响应是一个长时间运行的操作,您可以检查其完成情况。

导出特定种类或命名空间

如需导出种类和/或命名空间的特定子集,请提供包含种类和命名空间 ID 值的实体过滤条件

控制台

在控制台中,您可以选择所有种类或某一特定类型。 同样,您可以选择所有命名空间或某一特定命名空间。

如需指定要导出的命名空间和种类的列表,请改用 gcloud

  1. 转到 Google Cloud Console 中的 Datastore 导出页面。

    转到“Datastore 导出”页面

  2. 命名空间字段设置为 All Namespaces 或某一命名空间的名称。

  3. 种类字段设置为 All Kinds 或种类名称。

  4. 目标下,输入您的 Cloud Storage 存储分区的名称。

  5. 点击导出

控制台会打开实体并报告您的托管式导出请求是成功还是失败。

控制台还会显示查看状态按钮。 点击此按钮可打开 Cloud Shell 终端,该终端预先填充了查看操作状态所需的 gcloud 命令。

只要您想查看操作的状态,就可以运行此命令。

gcloud

    gcloud datastore export --kinds="KIND1,KIND2" --namespaces="(default),NAMESPACE2" gs://bucket-name --async
    

其中 bucket-name 是您的 Cloud Storage 存储分区的名称和可选前缀,例如 bucket-name/firestore-exports/export-name。您无法为其他导出操作重复使用相同的前缀。如果您不提供文件前缀,托管式导出服务会根据当前时间戳创建一个。

使用 --async 标志阻止 gcloud 等待操作完成。如果您省略 --async 标志,则可以输入 Ctrl+c 以停止等待某一操作。这不会取消该操作。

rest

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

  • project-id:您的项目 ID
  • bucket-name:Cloud Storage 存储分区的名称
  • kind:实体种类
  • namespace:命名空间 ID(对于默认命名空间 ID,使用 "")

HTTP 方法和网址:

POST https://datastore.googleapis.com/v1/projects/project-id:export

请求 JSON 正文:

    {
      "outputUrlPrefix": "gs://bucket-name",
      "entityFilter": {
        "kinds": ["kind"],
        "namespaceIds": ["namespace"],
      },
    }
    

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

您应会收到如下所示的 JSON 响应:

    {
      "name": "projects/project-id/operations/operation-id",
      "metadata": {
        "@type": "type.googleapis.com/google.datastore.admin.v1.ExportEntitiesMetadata",
        "common": {
          "startTime": "2019-09-18T21:17:36.232704Z",
          "operationType": "EXPORT_ENTITIES",
          "state": "PROCESSING"
        },
        "entityFilter": {
          "kinds": [
            "Task"
          ],
          "namespaceIds": [
            ""
          ]
        },
        "outputUrlPrefix": "gs://bucket-name/2019-09-18T21:17:36_82974"
      }
    }
    
该响应是一个长时间运行的操作,您可以检查其完成情况。

元数据文件

导出操作会为指定的每个命名空间-种类对创建一个元数据文件。元数据文件通常命名为 NAMESPACE_NAME_KIND_NAME.export_metadata。但是,如果某个命名空间或种类会创建出无效的 Cloud Storage 对象名称,则文件将命名为 export[NUM].export_metadata

元数据文件是 Protocol Buffers,可通过 protoc 协议编译器进行解码。例如,您可以对元数据文件进行解码,以确定导出文件包含的命名空间和种类:

    protoc --decode_raw < export0.export_metadata
    

导入所有实体

控制台

  1. 转到 Google Cloud Console 中的 Datastore 导入页面。

    转到“Datastore 导入”页面

  2. File 字段中,点击“浏览”并选择 overall_export_metadata 文件。

  3. 命名空间字段设置为 All Namespaces,并将种类字段设置为 All Kinds

  4. 点击导入

控制台会打开实体并报告您的托管式导入请求是成功还是失败。

控制台还会显示查看状态按钮。 点击此按钮可打开 Cloud Shell 终端,该终端预先填充了查看操作状态所需的 gcloud 命令。

只要您想查看操作的状态,就可以运行此命令。

gcloud

您可以使用 gcloud datastore import 命令导入之前使用托管式导出服务导出的所有实体。

    gcloud datastore import gs://bucket-name/file-path/file-name.overall_export_metadata --async

其中 bucket-name/file-path/file-name 是您的 Cloud Storage 存储分区中 overall_export_metadata 文件的路径。

使用 --async 标志阻止 gcloud 等待操作完成。如果您省略 --async 标志,则可以输入 Ctrl+c 以停止等待某一操作。这不会取消该操作。

rest

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

  • project-id:您的项目 ID
  • bucket-name:Cloud Storage 存储分区的名称
  • object-name:Cloud Storage 对象的名称(示例:2017-05-25T23:54:39_76544/2017-05-25T23:54:39_76544.overall_export_metadata

HTTP 方法和网址:

POST https://datastore.googleapis.com/v1/projects/project-id:import

请求 JSON 正文:

    {
      "inputUrl": "gs://bucket-name/object-name",
    }
    

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

您应会收到如下所示的 JSON 响应:

    {
      "name": "projects/project-id/operations/operation-id",
      "metadata": {
        "@type": "type.googleapis.com/google.datastore.admin.v1.ImportEntitiesMetadata",
        "common": {
          "startTime": "2019-09-18T21:25:02.863621Z",
          "operationType": "IMPORT_ENTITIES",
          "state": "PROCESSING"
        },
        "entityFilter": {},
        "inputUrl": "gs://bucket-name/2019-09-18T18:42:26_85726/2019-09-18T18:42:26_85726.overall_export_metadata"
      }
    }
    
该响应是一个长时间运行的操作,您可以检查其完成情况。

找到您的 overall_export_metadata 文件

您可以使用 Google Cloud Console 中的 Cloud Storage 浏览器确定用于导入位置的值:

打开 Cloud Storage 浏览器

您还可以列出并描述已完成的操作outputURL 字段显示 overall_export_metadata 文件的名称:

    "outputUrl": "gs://bucket-name/2017-05-25T23:54:39_76544/2017-05-25T23:54:39_76544.overall_export_metadata",
    

导入特定种类或命名空间

如需导入种类和/或命名空间的特定子集,请提供包含种类和命名空间 ID 值的实体过滤条件。

只有在使用实体过滤条件创建了导出文件时,才能指定种类和命名空间。您无法从包含所有实体的导出文件导入种类和命名空间的子集。

控制台

在控制台中,您可以选择所有种类或某一特定类型。 同样,您可以选择所有命名空间或某一特定命名空间。

如需指定要导入的命名空间和种类的列表,请改用 gcloud

  1. 转到 Google Cloud Console 中的 Datastore 导入页面。

    转到“Datastore 导入”页面

  2. File 字段中,点击“浏览”并选择 overall_export_metadata 文件。

  3. 命名空间字段设置为 All Namespaces 或某一特定命名空间。

  4. 种类字段设置为 All Kinds 或某一特定种类。

  5. 点击导入

控制台会打开实体并报告您的托管式导入请求是成功还是失败。

控制台还会显示查看状态按钮。 点击此按钮可打开 Cloud Shell 终端,该终端预先填充了查看操作状态所需的 gcloud 命令。

只要您想查看操作的状态,就可以运行此命令。

gcloud

    gcloud datastore import --kinds="KIND1,KIND2" --namespaces="(default),NAMESPACE2" gs://bucket-name/file-path/file-name.overall_export_metadata --async

其中 bucket-name/file-path/file-name 是您的 Cloud Storage 存储分区中 overall_export_metadata 文件的路径。

使用 --async 标志阻止 gcloud 等待操作完成。如果您省略 --async 标志,则可以输入 Ctrl+c 以停止等待某一操作。这不会取消该操作。

rest

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

  • project-id:您的项目 ID
  • bucket-name:Cloud Storage 存储分区的名称
  • object-name:Cloud Storage 对象的名称(示例:2017-05-25T23:54:39_76544/2017-05-25T23:54:39_76544.overall_export_metadata
  • kind:实体种类
  • namespace:命名空间 ID(对于默认命名空间 ID,使用 "")

HTTP 方法和网址:

POST https://datastore.googleapis.com/v1/projects/project-id:import

请求 JSON 正文:

    {
      "inputUrl": "gs://bucket-name/object-name",
      "entityFilter": {
        "kinds": ["kind"],
        "namespaceIds": ["namespace"],
      },
    }
    

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

您应会收到如下所示的 JSON 响应:

    {
      "name": "projects/project-id/operations/operation-id",
      "metadata": {
        "@type": "type.googleapis.com/google.datastore.admin.v1.ImportEntitiesMetadata",
        "common": {
          "startTime": "2019-09-18T21:51:02.830608Z",
          "operationType": "IMPORT_ENTITIES",
          "state": "PROCESSING"
        },
        "entityFilter": {
          "kinds": [
            "Task"
          ],
          "namespaceIds": [
            ""
          ]
        },
        "inputUrl": "gs://bucket-name/2019-09-18T21:49:25_96833/2019-09-18T21:49:25_96833.overall_export_metadata"
      }
    }
    
该响应是一个长时间运行的操作,您可以检查其完成情况。

管理长时间运行的操作

托管式导入和导出操作是长时间运行的操作。 这些方法调用可能需要大量时间才能完成。

在您开始执行导出或导入操作后,Datastore 模式会为操作分配唯一名称。您可以使用操作名称来删除、取消操作或检查操作状态。

操作名称的前缀为 projects/[PROJECT_ID]/databases/(default)/operations/,例如:

    projects/project-id/databases/(default)/operations/ASA1MTAwNDQxNAgadGx1YWZlZAcSeWx0aGdpbi1zYm9qLW5pbWRhEgopEg
    

不过,您可以在指定 describecanceldelete 命令的操作名称时省略前缀。

列出所有长时间运行的操作

如需列出长时间运行的操作,请使用 gcloud datastore operations list 命令。此命令会列出正在进行和已完成的操作。最近几天内完成的操作都会列出:

gcloud

    gcloud datastore operations list
    

rest

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

  • project-id:您的项目 ID

HTTP 方法和网址:

GET https://datastore.googleapis.com/v1/projects/project-id/operations

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

请参阅下方有关响应的信息。

例如,最近完成的导出操作会显示以下信息:

    {
      "operations": [
        {
          "name": "projects/project-id/operations/ASAyMDAwOTEzBxp0bHVhZmVkBxJsYXJ0bmVjc3Utc2Jvai1uaW1kYRQKKhI",
          "metadata": {
            "@type": "type.googleapis.com/google.datastore.admin.v1.ExportEntitiesMetadata",
            "common": {
              "startTime": "2017-12-05T23:01:39.583780Z",
              "endTime": "2017-12-05T23:54:58.474750Z",
              "operationType": "EXPORT_ENTITIES"
            },
            "progressEntities": {
              "workCompleted": "21933027",
              "workEstimated": "21898182"
            },
            "progressBytes": {
              "workCompleted": "12421451292",
              "workEstimated": "9759724245"
            },
            "entityFilter": {
              "namespaceIds": [
                ""
              ]
            },
            "outputUrlPrefix": "gs://bucket-name"
          },
          "done": true,
          "response": {
            "@type": "type.googleapis.com/google.datastore.admin.v1.ExportEntitiesResponse",
            "outputUrl": "gs://bucket-name/2017-05-25T23:54:39_76544/2017-05-25T23:54:39_76544.overall_export_metadata"
          }
        }
      ]
    }
    

描述单个操作

您可以列出单个长时间运行的操作的详细信息,而不是列出所有长时间运行的操作:

gcloud

使用 operations describe 命令可显示导出或导入操作的状态。

    gcloud datastore operations describe operation-name

rest

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

  • project-id:您的项目 ID
  • operation-name:操作名称

HTTP 方法和网址:

GET https://datastore.googleapis.com/v1/projects/project-id/operations/operation-name

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

您应会收到如下所示的 JSON 响应:

    
    {
      "name": "projects/project-id/operations/ASA3ODAwMzQxNjIyChp0bHVhZmVkBxJsYXJ0bmVjc3Utc2Jvai1uaW1kYRQKLRI",
      "metadata": {
        "@type": "type.googleapis.com/google.datastore.admin.v1.ExportEntitiesMetadata",
        "common": {
          "startTime": "2019-10-08T20:07:28.105236Z",
          "endTime": "2019-10-08T20:07:36.310653Z",
          "operationType": "EXPORT_ENTITIES",
          "state": "SUCCESSFUL"
        },
        "progressEntities": {
          "workCompleted": "21",
          "workEstimated": "21"
        },
        "progressBytes": {
          "workCompleted": "2272",
          "workEstimated": "2065"
        },
        "entityFilter": {},
        "outputUrlPrefix": "gs://bucket-name/2019-10-08T20:07:28_28481"
      },
      "done": true,
      "response": {
        "@type": "type.googleapis.com/google.datastore.admin.v1.ExportEntitiesResponse",
        "outputUrl": "gs://bucket-name/2019-10-08T20:07:28_28481/2019-10-08T20:07:28_28481.overall_export_metadata"
      }
    }
    

估计完成时间

操作运行时,请查看 state 字段的值,了解操作的总体状态。

用于获取运行时间较长的操作状态的请求也会返回指标 workEstimatedworkCompleted。返回的每个指标均包含字节数和实体数。workEstimated 基于数据库统计信息估算操作将处理的总字节数和总实体数。workCompleted 显示到目前为止已处理的字节数和实体数。操作完成后,workCompleted 会反映实际处理的总字节数和总实体数,可能大于 workEstimated 的值。

workCompleted 除以 workEstimated 可得出粗略的进度估算值。该估计可能不准确,因为它取决于统计信息收集是否存在延迟。

例如,下面是一个导出操作的进度状态:

    {
      "operations": [
        {
          "name": "projects/project-id/operations/ASAyMDAwOTEzBxp0bHVhZmVkBxJsYXJ0bmVjc3Utc2Jvai1uaW1kYRQKKhI",
          "metadata": {
            "@type": "type.googleapis.com/google.datastore.admin.v1.ExportEntitiesMetadata",
            ...
            "progressEntities": {
              "workCompleted": "1",
              "workEstimated": "3"
            },
            "progressBytes": {
              "workCompleted": "85",
              "workEstimated": "257"
            },
            ...
    

操作完成后,操作说明将包含 "done": true。查看 state 字段的值,了解操作的结果。如果没有在响应中设置 done 字段,则其值为 false。对于进行中的操作,不要依赖 done 值是否存在。

取消操作

使用 operations cancel 命令可停止正在进行的操作:

    gcloud datastore operations cancel operation-name
    

取消正在进行的操作并不会撤消操作。取消的导出操作会在 Cloud Storage 中留下已导出的文档,而取消的导入操作会留下已对数据库进行的更新。您无法导入部分完成的导出文件。

删除操作

使用 operations delete 命令可移除 operations list 输出中的某项操作。此命令不会从 Cloud Storage 中删除导出文件。

    gcloud datastore operations delete operation-name
    

托管导出和导入的结算和价格

在使用托管式导出和导入服务前,您需要为 Google Cloud 项目启用结算功能。导出和导入操作通过以下方式计入 Google Cloud 费用:

导出和导入操作的费用不会计入 App Engine 支出限额。导出或导入操作在完成之前不会触发任何 Google Cloud 预算提醒。同样,操作完成后,在导出或导入操作期间执行的读写数会计入您的每日配额

权限

如需运行导出和导入操作,您的用户帐号和项目的默认服务帐号需要具备下述 Cloud Identity and Access Management 权限。

用户帐号权限

发起该操作的用户帐号或服务帐号需要 datastore.databases.exportdatastore.databases.import Cloud IAM 权限。如果您是 Project Owner,则您的帐号拥有所需的权限。如果不是,以下 Cloud IAM 角色可授予必要权限:

  • Datastore Owner
  • Datastore Import Export Admin

Project Owner 可以按照授予访问权限中的步骤授予其中一个角色。

默认服务帐号权限

每个 Google Cloud 项目都会自动创建一个名为 PROJECT_ID@appspot.gserviceaccount.com 的默认服务帐号。导出和导入操作使用此服务帐号授权 Cloud Storage 操作。

您的项目的默认服务帐号需要访问导出或导入操作中使用的 Cloud Storage 存储分区。如果您的 Cloud Storage 存储分区与您的 Datastore 模式数据库位于同一项目中,则默认情况下,默认服务帐号能够访问该存储分区

如果 Cloud Storage 存储分区位于其他项目中,则您必须为默认服务帐号授予对 Cloud Storage 存储分区的访问权限。

向默认服务帐号分配角色

您可以使用 gsutil 命令行工具分配以下角色之一。例如,如需为默认服务帐号分配 Storage Admin 角色,请运行:

    gsutil iam ch serviceAccount:[PROJECT_ID]@appspot.gserviceaccount.com:roles/storage.admin \
        gs://[BUCKET_NAME]
    

或者,您也可以使用 Cloud Console 分配此角色

导出操作

对于涉及其他项目中的存储分区的导出操作,请修改存储分区的权限,将以下 Cloud Storage 角色之一分配给您的 Datastore 模式数据库所属项目的默认服务帐号:

  • Storage Admin
  • Storage Object Admin
  • Storage Legacy Bucket Writer

您还可以创建具备以下权限的 Cloud IAM 自定义角色

  • storage.buckets.get
  • storage.objects.create
  • storage.objects.list

导入操作

对于涉及其他项目中的 Cloud Storage 存储分区的导入操作,请修改存储分区的权限,将以下 Cloud Storage 角色之一分配给您的 Datastore 模式数据库所属项目的默认服务帐号:

  • Storage Admin
  • Storage Object Viewer 和 Storage Legacy Bucket Reader

您还可以创建具备以下权限的 Cloud IAM 自定义角色

  • storage.buckets.get
  • storage.objects.get

与 Datastore 管理员备份的区别

如果您之前使用过 Datastore 管理员控制台进行备份,则应注意以下差异:

  • 托管式导出所创建的导出操作不会出现在 Datastore 管理员控制台中。托管式导出和导入是一项新服务,不会与 App Engine 的备份和恢复功能共享数据(您可通过 Cloud Console 管理此功能)。

  • 托管式导出和导入服务不支持与 Datastore 管理员备份相同的元数据,也不会将进度状态存储在数据库中。如需了解如何检查导出和导入操作的进度,请参阅管理长时间运行的操作

  • 您无法查看托管式导出和导入操作的服务日志。

  • 托管式导入服务向后兼容 Datastore 管理员备份文件。您可以使用托管式导入服务导入 Datastore 管理员备份文件,但无法使用 Datastore 管理员控制台导入托管式导出操作的输出。

导入到 BigQuery

如需通过托管式导出服务将数据导入 BigQuery,请参阅加载 Datastore 导出服务数据

如果在未指定实体过滤条件的情况下导出了数据,则该数据无法加载到 BigQuery 中。如果您想要将数据导入到 BigQuery,则您的导出请求的实体过滤条件中必须包含一个或多个种类名称。

BigQuery 列限制

BigQuery 对表格施加的列数上限为 10000。 导出操作会为每个种类生成 BigQuery 表架构。在此架构中,种类实体内的每个唯一属性都会变为架构列。

如果种类的 BigQuery 架构超过 10000 列,则导出操作会尝试将嵌入式实体视为 Blob,从而保持在列限制以下。如果此转化使架构中的列数低于 10000,您可以将数据加载到 BigQuery 中,但无法查询嵌入式实体中的属性。 如果列数仍然超过 10000,则导出操作不会为该种类生成 BigQuery 架构,而且您无法将其数据加载到 BigQuery 中。