序列化

序列化仅在专业版企业版计划中可用(包括自托管和Metabase Cloud)。

一旦你真正开始使用Metabase,你可能会启动多个Metabase实例。你可能有几个测试或开发实例和一些生产实例,或者你可能为每个办公室或地区使用一个单独的Metabase。

为了帮助你在这种情况下,Metabase有一个序列化功能,它允许你创建一个Metabase内容的导出,然后可以将其导入一个或多个Metabase。

导出将源Metabase的内容序列化为YAML文件。

导入将读取这些导出的YAML文件,并根据这些YAML文件中序列化的内容在目标Metabase中创建或更新项。

运行这些导出导入命令有两种方法

我们感兴趣的是如何改进序列化以适应您的流程。支持现有问题,让我们知道这对您很重要。如果尚无相关问题,请创建一个问题并告诉我们您需要什么。

序列化用例

  • 预发布环境。通过从Metabase预发布实例导出并将它们导入您的生产实例(s)来启用重要仪表板的预发布到生产流程。
  • 版本控制。将导出的文件存入版本控制并审计它们的变化,因为导出中包含的YAML文件非常易于阅读。
  • 将资产复制到其他Metabase实例。从源Metabase导出“模板”数据并将其导入一个或多个目标实例。

查看我们的指南以

序列化不适用于如复制资产或交换同一Metabase实例内的数据源等用例。如果您正在同一实例内使用序列化来复制资产,请查看导出如何工作导入如何工作以及序列化的其他用途中的您的用例说明。

导出如何工作

导出什么

Metabase只会在导出中包含一些工件

  • 集合(但除非在导出选项中明确指定,否则个人集合不会导出)
  • 仪表板
  • 保存的问题
  • 操作
  • 模型
  • 指标
  • SQL代码片段
  • 数据模型和表元数据
  • 细分
  • 问题和仪表板的公共共享设置
  • 一般Metabase设置
  • 事件和时间线
  • 数据库连接字符串(只有当通过导出选项指定时才包含)(#customize-what-gets-exported)。

Metabase将工件导出到YAML文件目录。导出包括

  • 包含各种Metabase实体YAML文件的目录。一个示例导出可能包括以下目录,具体取决于您导出什么以及您的Metabase内容

    • 动作
    • 集合
      • 卡片
      • 仪表板
      • 时间线
    • 数据库

    通过API序列化时,导出目录将被压缩成.tar.gz文件

  • 一个包含一些Metabase全局设置settings.yaml文件

默认情况下,不包括数据库连接细节,但您可以通过配置导出来包含它们。

导出的通用Metabase设置

以下是Metabase在settings.yaml文件中导出的通用设置列表。有关Metabase设置的更多信息,请参阅配置Metabase

humanization-strategy
native-query-autocomplete-match-style
site-locale
report-timezone-short
report-timezone-long
application-name
enable-xrays
show-homepage-pin-message
source-address-header
enable-nested-queries
custom-geojson-enabled
start-of-week
custom-geojson
available-timezones
unaggregated-query-row-limit
aggregated-query-row-limit
hide-embed-branding?
search-typeahead-enabled
enable-sandboxes?
application-font
available-locales
landing-page
enable-embedding
application-colors
application-logo-url
application-favicon-url
show-homepage-xrays
show-metabot
enable-whitelabeling?
show-homepage-data
site-name
application-font-files
loading-message
report-timezone
persisted-models-enabled
enable-content-management?
subscription-allowed-domains
breakout-bins-num
available-fonts
custom-formatting

自定义要导出的内容

您可以根据需要自定义导出内容。您可以告诉Metabase

  • 导出特定集合
  • 不导出集合
  • 不导出Metabase设置
  • 不导出表元数据
  • 包含示例字段值(默认不包含)
  • 包含数据库连接细节(默认不包含)

请参阅CLI命令中的导出参数API调用中的导出参数

序列化问题的示例

问题可以在集合目录的cards目录中找到。以下是一个使用SQL编写的带有字段过滤器和区域图可视化的示例问题YAML文件

为了保留原生查询的多行格式,请从原生查询中删除尾随空格。如果您的原生查询有尾随空格,YAML会将您的查询转换为单个字符串字面量(这只会影响展示,而不会影响功能)。

name: Products by week
description: Area chart of products created by week
entity_id: r6vC_vLmo9zG6_r9sAuYG
created_at: "2024-05-08T19:10:24.348808Z"
creator_id: [email protected]
display: area
archived: false
collection_id: onou5H28Wvy3kWnjxxdKQ
collection_preview: true
collection_position: null
query_type: native
dataset: false
cache_ttl: null
database_id: Sample Database
table_id: null
enable_embedding: false
embedding_params: null
made_public_by_id: null
public_uuid: null
parameters:
  - default:
      - Gizmo
    id: c37d2f38-05fa-48c4-a208-19d9dba803c6
    name: Pick a category
    slug: category_filter
    target:
      - dimension
      - - template-tag
        - category_filter
    type: string/=
parameter_mappings: []
dataset_query:
  database: Sample Database
  native:
    query: |-
      SELECT
        category,
        date_trunc ('week', created_at) AS "Week",
        count(*) AS "Count"
      FROM
        products
      WHERE
        
      GROUP BY
        category,
        "Week"
    template-tags:
      category_filter:
        default:
          - Gizmo
        dimension:
          - field
          - - Sample Database
            - PUBLIC
            - PRODUCTS
            - CATEGORY
          - base-type: type/Text
        display-name: Pick a category
        id: c37d2f38-05fa-48c4-a208-19d9dba803c6
        name: category_filter
        type: dimension
        widget-type: string/=
  type: native
result_metadata:
  - base_type: type/Text
    display_name: CATEGORY
    effective_type: type/Text
    field_ref:
      - field
      - CATEGORY
      - base-type: type/Text
    name: CATEGORY
    semantic_type: null
  - base_type: type/DateTime
    display_name: Week
    effective_type: type/DateTime
    field_ref:
      - field
      - Week
      - base-type: type/DateTime
    name: Week
    semantic_type: null
  - base_type: type/BigInteger
    display_name: Count
    effective_type: type/BigInteger
    field_ref:
      - field
      - Count
      - base-type: type/BigInteger
    name: Count
    semantic_type: type/Quantity
visualization_settings:
  column_settings: null
  graph.dimensions:
    - Week
    - CATEGORY
  graph.metrics:
    - Count
serdes/meta:
  - id: r6vC_vLmo9zG6_r9sAuYG
    label: products_created_by_week
    model: Card
initially_published_at: null
metabase_version: v1.49.7 (f0ff786)
type: question

Metabase使用实体ID来标识和引用Metabase项目

Metabase为每个Metabase项目(仪表板、问题、模型、集合等)分配一个唯一的实体ID。实体ID使用NanoID格式

您可以在导出的YAML文件中的entity_id字段中看到项目的实体ID。例如,在序列化问题的示例中,您将看到该问题的实体ID

entity_id: r6vC_vLmo9zG6_r9sAuYG

此ID也出现在serdes/meta → id字段中(这些ID必须匹配)

serdes/meta:
  - id: r6vC_vLmo9zG6_r9sAuYG

为了区分具有相同名称的实体,Metabase在导出实体的文件和目录名称中包含实体ID。

r6vC_vLmo9zG6_r9sAuYG_products_by_week.yaml
IA96oUzmUbYfNFl0GzhRj_accounts_model.yaml
KUEGiWvoBFEc5oGQCEnPg_converted_customers.yaml

例如,在序列化问题的示例中,您可以看到字段collection_id

collection_id: onou5H28Wvy3kWnjxxdKQ

此ID指的是保存问题的集合。在实际导出中,您将能够找到一个以其实体ID开头的YAML文件,例如:onou5H28Wvy3kWnjxxdKQ

数据库、模式、表和字段通过名称标识

默认情况下,Metabase导出一些数据库和数据模型设置。导出默认不包含数据库连接字符串。您可以明确包含数据库连接字符串。您也可以选择完全排除数据模型。

Metabase 将数据库和表序列化到 databases 目录中。它将为每个数据库、表、字段、段和度量创建 YAML 文件。

数据库、表和字段通过其名称引用(与通过实体 ID 引用的 Metabase 特定项目不同)。

例如,在 序列化问题的示例 中,有几个 YAML 键引用了“示例数据库”。

database_id: Sample Database
---
dataset_query:
  database: Sample Database

在示例中字段过滤器(category_filter:)的描述中,可以看到对用于填充过滤器选项的字段的引用。

dimension:
  - field
  - - Sample Database
    - PUBLIC
    - PRODUCTS
    - CATEGORY

它指的是“示例数据库”中 PUBLIC 架构下的 PRODUCTS 表中的 CATEGORY 字段。在 databases 目录中序列化的 Sample Database 也将包括此字段和表的 YAML 文件。

导入工作原理

在导入过程中,Metabase 将读取提供的 YAML 文件,并根据 YAML 规范创建项目。《序列化问题的示例》说明了 Metabase 如何记录重建项目所需的信息。

Metabase 在导入过程中不会从目标实例中删除项目,但会覆盖已经存在的项目。

Metabase 依赖于 实体 ID 来确定要创建或覆盖的项目,以及项目之间的关系。在将内容导入已有内容的实例时,请注意

  • 如果您导入一个具有不存在于目标 Metabase 中的 entity_id 的项目,Metabase 将创建一个新的项目。

  • 如果您导入一个在目标 Metabase 中已经存在的 entity_id 的项目,现有项目将被覆盖。

    特别是,这意味着如果您导出一个问题,然后在导出的 YAML 文件中进行更改(例如,通过直接编辑 name 字段来重命名问题),然后导入编辑后的文件,Metabase 将尝试将您所做的更改应用到 YAML 上。

  • 如果您导入一个具有空白 entity_id(以及空白 serdes/meta → id)的项目,Metabase 将创建一个新的项目。

  • 在 YAML 中引用的所有项目和数据源必须在目标 Metabase 中已存在,或者包含在导入中。

    例如,如果导出的 YAML 中有字段 collection_id: onou5H28Wvy3kWnjxxdKQ,则目标实例中必须已经存在 onou5H28Wvy3kWnjxxdKQ 的集合,或者必须有一个具有此 ID 的集合导出 YAML 文件。

序列化最佳实践

使用与源实例和目标实例相同的 Metabase 版本

目前,只有当源和目标 Metabase 有相同的主版本时,序列化才能工作。如果您正在使用 CLI 序列化命令,您用于运行序列化命令的 .jar 文件的版本应与源和目标 Metabase 版本匹配。

如果您使用 H2 作为应用程序数据库,您需要在导入或导出之前停止 Metabase

如果您使用 Postgres 或 MySQL 作为应用程序数据库,您可以在 Metabase 运行时导入和导出。

避免使用序列化进行备份

仅作参考:序列化 不是 用来备份您的 Metabase。

请参阅 备份 Metabase

如果您想从随Metabase提供的默认H2数据库迁移到MySQL/Postgres数据库,请使用迁移指南

您需要手动添加许可证令牌

Metabase将您的许可证令牌排除在导出之外,因此如果您运行多个Metabase企业版的实例,您需要手动将许可证令牌添加到目标Metabase实例中,无论是通过Metabase用户界面,还是通过环境变量

Metabase将日志添加到导出和导入过程中

导出:Metabase将日志添加到压缩目录中的export.log文件中。

导入:您可以使用-o -标志将日志直接导出到终端,或者使用-o import.log将其保存到文件。

使用CLI命令进行序列化

在Metabase Cloud上序列化数据,请使用导入和导出API端点

Metabase提供exportimport CLI命令。

有关序列化的通用信息,请参阅导出是如何工作的导入是如何工作的序列化最佳实践

使用CLI进行导出

要导出Metabase实例的内容,请切换到运行Metabase JAR文件的目录,并运行以下命令:

java -jar metabase.jar export dir_name

其中dir_name可以是您想要的任何目录名。

export选项

要查看export选项的列表,请使用help命令。

java -jar metabase.jar help export

它将运行并打印类似以下内容:

export path & options
	 Serialize Metabase instance into directory at `path`.
	 Options:
	   -c, --collection ID             Export only specified ID; may occur multiple times.
	   -C, --no-collections            Do not export any content in collections.
	   -S, --no-settings               Do not export settings.yaml
	   -D, --no-data-model             Do not export any data model entities; useful for subsequent exports.
	   -f, --include-field-values      Include field values along with field metadata.
	   -s, --include-database-secrets  Include database connection details (in plain text; use caution).

--collection

默认情况下,Metabase将包括所有集合(除了个人集合)在导出中。要包括个人集合,您必须使用--collection标志显式添加它们。

--collection标志(别名-c)允许您通过ID指定一个或多个要包含在导出中的集合。您可以在集合的URL中找到集合ID,例如,对于位于your-metabase.com/collection/42-terraforming-progress的集合,ID将是42

如果您想指定多个集合,请使用逗号分隔ID。例如:

java -jar metabase.jar export export_name --collection 1,2,3

--no-collections

--no-collections标志(别名-C)告诉Metabase排除所有集合从导出。

--no-settings

--no-settings标志(别名-S)告诉Metabase排除包含全局设置settings.yaml文件,该文件默认导出。

--no-data-model

--no-data-model标志(别名-D)告诉Metabase排除导出中的表元数据设置。管理员在管理设置的表元数据标签页中定义元数据设置。

--include-field-values

标志 --include-field-values(别名 -f)指示 Metabase 包含字段值的样本值,这些值用于 Metabase 显示下拉菜单。默认情况下,Metabase 排除这些样本字段值。

--include-database-secrets

标志 --include-database-secrets(别名 -s)指示 Metabase 包含连接详情,包括数据库用户名和密码。默认情况下,Metabase 排除这些数据库连接密钥。如果您不使用此标志,您需要手动在目标 Metabase 中输入凭据。

使用 CLI 导入

要将导出的项目导入到 Metabase 实例中,请转到运行目标 Metabase 的目录(您要导入的 Metabase),并使用以下命令,其中 path_to_export 是要导入的导出路径

java -jar metabase.jar import path_to_export

目前,您只能将导出的项目导入到与同一版本 Metabase 创建的 Metabase 实例中。

import 选项

大多数选项是在从 Metabase 导出数据时定义的。要查看导入标志列表,请运行

java -jar metabase.jar help import

它将打印出

import path & options
         Load serialized Metabase instance as created by the [[export]] command from directory `path`.

通过 API 进行序列化

与 CLI 序列化命令一样,这些端点仅适用于 ProEnterprise 计划。

您可以通过 Metabase 的 API 导入和导出序列化的 Metabase 数据,这使得在 Metabase Cloud 部署中实现序列化成为可能。

有两个端点

  • POST /api/ee/serialization/export
  • POST /api/ee/serialization/import

对于 /export 端点,我们使用 POST 而不是 GET。导出操作不会修改您的 Metabase,但操作耗时且强度大,因此我们使用 POST 以防止意外导出。

目前,这些端点是同步的。如果序列化过程耗时过长,请求可能会超时。在这种情况下,我们建议使用 CLI 命令。

有关序列化的通用信息,请参阅导出是如何工作的导入是如何工作的序列化最佳实践

API 导出参数

您可以将可选参数附加到 Metabase,以指定要从导出中包含或排除的内容。您还可以组合参数(当然,不包括 all_collections 和选择性的集合)。

因此,假设您正在本地测试(localhost),并且您想从导出中排除所有集合,您将按如下格式格式化 URL

https://127.0.0.1:3000/api/ee/serialization/export?all_collections=false

您可以将多个参数包括在内,参数之间用 & 分隔。例如,要排除导出中的设置和数据模型

https://127.0.0.1:3000/api/ee/serialization/export?data_model=false&settings=false

collection

类型:整数数组。

默认值:除非将 all_collections 设置为 false,否则 Metabase 将导出所有集合。

要选择要导出的集合,请包括集合 ID。例如,要包括集合 12

collection=1&collection=2

all_collections

类型:布尔值。

默认值:true(除非您使用 collection 指定子集集合)。

要排除所有集合

all_collections=false

settings

类型:布尔值。

默认值:true

要排除包含全局设置的 settings.yaml 文件

settings=false

data_model

类型:布尔值。

默认值:true

要排除 表元数据

data_model=false

field_values

类型:布尔值。

默认: false

包括字段的示例值,Metabase 使用这些值来显示下拉菜单

field_values=true

database_secrets

类型:布尔值。

默认: false

包括数据库连接详情,例如数据库用户名和密码

database_secrets=true

dirname

类型:字符串。

默认: <实例名称>-<YYYY-MM-dd_HH_mm>

指定不同的目录

dirname=name_of_your_directory

在通过 API 调用序列化时,您必须压缩您的文件

为了控制通过网络传输的文件大小,exportimport 端点都期望 GZIP 压缩的 Tar 文件(.tgz)。

压缩目录

要压缩目录(例如,名为 metabase_data 的目录)。

tar -czf  metabase_data.tgz metabase_data

解压目录

解压/解压缩目录

tar -xvf  metabase_data.tgz

序列化 API 示例

步骤 1:设置 API 密钥

  1. 创建一个 API 密钥
  2. 将密钥分配给管理员组

步骤 2:导出

  1. 发送一个 curl 请求来导出数据
curl \
  -H 'x-api-key: YOUR_API_KEY' \
  -X POST 'http://your-metabase-url/api/ee/serialization/export' \
  -o metabase_data.tgz

YOUR_API_KEY 替换为您的 API 密钥,将 your-metabase-url 替换为您的 Metabase 实例 URL。

我们使用 POST 而不是 GET 来请求 /export 端点。

此命令将下载名为 metabase_data.tgz 的 GZIP 压缩 Tar 文件。

  1. 解压压缩文件
tar -xvf metabase_data.tgz

解压后的目录将命名为类似 metabase-yyyy-MM-dd_HH-mm 的名称,其中包含导出的日期和时间。

步骤 3:导入

  1. 压缩包含序列化 Metabase 应用程序数据的目录

假设您有一个名为 metabase_data 的目录,其中包含 Metabase 应用程序数据的 YAML 文件。在将文件导入目标 Metabase 之前,您需要压缩这些文件。

tar -czf metabase_data.tgz metabase_data
  1. /api/ee/serialization/import 发送 POST 请求。

从您存储 GZIP 压缩文件的目录运行

curl -X POST \
  -H 'x-api-key: YOUR_API_KEY' \
  -F file=@metabase_data.tgz \
  'http://your-metabase-url/api/ee/serialization/import' \
  -o -

YOUR_API_KEY 替换为您的 API 密钥,将 your-metabase-url 替换为您的 Metabase 实例 URL。使用 -o - 选项将在终端中输出日志。

如果您将 Metabase 数据导入与导出相同的 Metabase,您将覆盖现有的问题、仪表板等。请参阅 导入如何工作

序列化的其他用途

序列化旨在用于版本控制、预发布到生产流程以及将资产复制到其他 Metabase 实例。虽然可以使用序列化处理其他用例(例如,在单个实例内复制资产),但我们官方不支持这些用例。

我们提供了一些如何处理这些不受支持的用例的指导,但您应自行承担风险。我们强烈建议您首先在一个非生产实例上测试涉及序列化的任何流程,如果有任何问题,请联系 [email protected]

在同一个 Metabase 内使用序列化来复制内容

使用序列化来复制内容并不简单,因为您需要处理所有要复制的项目以及与其相关联的项目 实体ID,以避免覆盖现有数据。

在开始这次危险之旅之前,请查看 导出如何工作导入如何工作,如有任何问题,请联系 [email protected]

您需要注意

  • 导入具有已存在实体ID的项目将覆盖现有项目。要使用现有的YAML文件创建新项目,您需要:a) 创建新的实体ID或b) 清除实体ID。
  • 两个项目不能有相同的实体ID。
  • 在YAML文件中,entity_idserdes/meta → id 字段应匹配。
  • 如果YAML文件中项目的entity_idserdes/meta → id 字段为空,Metabase将创建一个带有新实体ID的新项目。
  • 项目和数据源应已存在于目标Metabase中,或者包含在导入中。

    例如,一个集合可以包含一个仪表板,该仪表板包含一个基于模型构建的问题,该模型引用数据源。所有这些依赖项必须包含在导入中或已存在于目标实例中。

    这意味着您可能需要进行多阶段导出/导入:首先在Metabase中创建一些需要的项目(如集合),然后导出以获取它们的实体ID,然后导出要复制的项目,并在引用它们的项目中使用这些ID。

例如,要复制一个仅包含直接基于原始数据构建的问题的集合(不包括基于模型或其他已保存问题的),不更改问题的数据源,可以使用以下过程

  1. 在Metabase中创建一个“模板”集合,并添加您想要复制的项目。
  2. 在Metabase中创建一个新的集合,该集合将作为复制项目的目标。
  3. 导出模板集合和目标集合(您可以使用导出参数仅导出一些集合)。导出的模板问题的YAML文件将有自己的实体ID,并引用模板集合的实体ID。
  4. 从其导出中获取目标集合的实体ID。
  5. 在模板集合导出的问题的YAML文件中

    • 清除问题的entity_idserdes/meta → id 字段的值。这将确保模板问题不会被覆盖,相反,Metabase将创建新的问题。
    • 将模板集合的collection_id 引用替换为新集合的ID
  6. 导入编辑后的文件。

此过程假定复制的所有问题都将使用相同的数据源。您可以将此与切换实例内问题的数据源结合使用,为每个复制的集合使用不同的数据源。

如果您想一次性创建一个集合的多个副本,那么您不必为每个副本重复此过程,您可以创建自己的目标实体ID(可以是任何使用NanoID格式的字符串),复制所有模板YAML文件,并用您创建的实体ID替换模板实体ID及其任何引用。

如果您的集合包含仪表板、模型和其他可以添加依赖项的项目,这个过程可能会变得更复杂——您需要处理每个依赖项。我们强烈建议您首先在一个非生产环境的Metabase上测试您的序列化,如果您需要任何帮助,请联系[email protected]

使用序列化在单个实例中交换问题的数据源

如果您想更改Metabase中一些问题的数据源——例如,仅更改单个集合中的问题——您可以手动序列化这些问题,然后编辑导出的YAML文件。

如果您想将建立在数据库A上的所有问题切换到使用数据库B,并且数据库B具有与数据库A完全相同的模式,您不需要使用序列化:您只需在“管理员 > 数据库”中交换连接字符串即可。

您的数据库必须具有相同的引擎,理想情况下它们应该具有相同的模式。

您需要注意

  • 在Metabase中,数据库、表和字段是通过名称进行引用的(请参阅)
  • 默认情况下不会导出数据库连接详情。要导出数据库连接详情,您需要在导出参数中指定
  • 引用的数据库、表和字段应已在目标Metabase中存在,或包含在导入中。

例如,如果您想将“电影评论”集合中的所有问题切换到使用“浪漫”数据库而不是“恐怖”数据库,并且两个数据库具有相同的模式,您可以按照以下过程操作

  1. 在Metabase中,在“管理员 > 数据库”中添加一个新的数据库连接,并将其命名为“浪漫”。
  2. 导出“电影评论”集合。

    您可以让Metabase导出单个集合,或者您可以导出所有集合,然后只处理“电影评论”集合文件夹中的文件。

  3. 在此集合项的YAML文件中,将所有对“恐怖”数据库的引用替换为对“浪漫”数据库的引用。
  4. 导入编辑后的文件。

导入将覆盖原始问题。如果您想创建使用不同数据源的新问题,可以将此过程与使用序列化在同一个Metabase中复制资产结合起来。

此过程假设新数据源具有完全相同的模式。如果模式不同,您还需要替换所有对表和字段的引用。此过程可能很复杂且容易出错,因此我们强烈建议您首先在一个非生产实例上测试您的序列化,如果您需要任何帮助,请联系[email protected]

从旧序列化命令迁移

如果您是从Metabase版本46.X或更旧版本升级,以下是需要了解的内容

  • export”命令替换了“dump”命令。
  • import”命令替换了“load”命令。

以下是一些其他更改要点

  • 导出的 YAML 文件结构略有不同
    • Metabase 会为每个文件前缀添加一个 24 位的实体 ID(例如 IA96oUzmUbYfNFl0GzhRj_accounts_model.yaml)。您可以在导出之前运行 Metabase 命令来删除实体 ID
    • 文件树略有不同。
  • 要序列化个人收藏夹,只需在 -c 选项(即 --collection)后面的逗号分隔 ID 列表中包含个人收藏夹 ID 即可。

如果您编写了自动化序列化的脚本,您需要

  • 使用升级后的 Metabase 重新序列化您的 Metabase(使用新的 exportimport 命令)。请注意,序列化仅在您使用相同的 Metabase 版本导出和导入 Metabase 时才会生效。
  • 更新脚本以使用新命令。请参阅新的 导出选项
  • 如果您的脚本对导出的 YAML 文件进行任何后处理,您可能需要更新您的脚本以适应略有不同的目录和 YAML 文件结构。

进一步阅读

阅读其他 Metabase 版本的文档

想改进这些文档? 提出更改。