变更数据流概览

变更数据流可以近乎实时地监控并流式传输 Spanner 数据库的数据更改(插入、更新和删除)。

本页面简要介绍了 Spanner 变更流:它们的用途和工作原理。如需了解如何在数据库中创建和管理变更数据流并将其与其他服务连接,请点击后续步骤中的链接。

变更数据流的用途

变更流提供了一种灵活、可伸缩的方式来将数据变更流式传输到其他服务。常见用例包括:

  • 将 Spanner 数据更改复制到数据仓库(例如 BigQuery)以进行分析。

  • 基于发送到消息队列的数据更改(例如 Pub/Sub)触发应用逻辑。

  • 将数据更改存储在 Cloud Storage 中,以实现合规性或归档目的。

变更数据流配置

Spanner 将变更数据流视为架构对象,就像表和索引一样。因此,您可以使用 DDL 语句创建、修改和删除更改流,并且可以像查看其他 DDL 管理的架构对象一样查看数据库的更改流

您可以配置变更数据流以监控整个数据库中的数据更改,或将其范围限定为特定表和列。一个数据库可以有多个变更数据流,而一个特定表或列可以在限制范围内有多个监控它的数据流。

您还可以配置变更数据流来指定数据保留期限值捕获类型过滤基于 TTL 的删除操作表修改过滤条件

发布用于创建变更数据流的 DDL 会启动一项长时间运行的操作。完成后,新变更数据流会立即开始监控分配给它的表和列。

隐式监控表和列

监控整个表的变更数据流会隐式监控该表中的所有列,即使该表定义已更新也是如此。例如,当您向该表添加新列时,变更数据流会自动开始监控这些新列,而无需对该变更数据流的配置进行任何修改。同样,变更数据流会自动停止监控从该表中删除的任何列。

整个数据库变更数据流的工作原理相同。它们会隐式监控每个表中的每个列,自动监控创建变更数据流后添加的任何表或列,并停止监视丢弃的任何表或列。

显式监控表和列

如果您将变更数据流配置为仅监控某个表中的特定列,而后来又向该表中添加了某些列,那么除非您重新配置该变更数据流,否则变更数据流将不会开始监控这些列。

数据库的架构将变更数据流视为其明确监控的任何列或表的依赖对象。在删除任何此类列或表之前,您必须手动将其从明确监控的变更数据流的配置中移除。

可变更数据流的数据变更类型

变更数据流监控的数据更改包括对其监控的表和列进行的所有插入、更新和删除操作。这些更改可能来自于:

变更数据流只能监控用户创建的列和表中的数据变更。而不会监视索引、视图、其他变更数据流或系统表(如信息架构或统计信息表)。变更流不会监控生成的列,除非相应列是主键的一部分。系统始终会跟踪主键列。

此外,变更数据流不会监控架构更改或由架构更改直接导致的任何数据更改。例如,监控整个数据库的变更流不会将删除表视为数据更改,即使此操作会从数据库中移除该表的所有数据,也是如此。

Spanner 如何写入和存储变更数据流

每次在变更数据流监控的列中检测到数据变更时,Spanner 都会将数据变更记录写入其内部存储空间。它会在同一事务中与数据更改同步执行此操作。Spanner 将这两种写入放在同一个位置,以便它们由同一服务器处理,从而最大限度地减少写入处理。

数据更改记录的内容

变更数据流写入的每条数据变更记录都包含以下与数据变更相关的信息:

  • 受影响表的名称

  • 标识已更改行的主键的名称、值和数据类型

  • 根据变更数据流定义捕获的已更改行列的名称和数据类型。

  • 行列的旧值。旧值的可用性及其跟踪的内容(可以仅修改列,也可以是跟踪的整个行)取决于用户配置的值捕获类型

  • 行列的新值。新值的可用性及其跟踪的内容取决于用户配置的值捕获类型

  • 修改类型(插入、更新或删除)

  • 提交时间戳

  • 交易 ID

  • 记录序列号

  • 数据更改记录的值捕获类型。

如需深入了解数据更改历史记录的结构,请参阅数据更改历史记录

数据保留

变更数据流会将其数据变更记录保留一到七天。您可以使用 DDL 在最初创建变更数据流时指定数据保留限制(一天默认值除外),或者在将来的任何时间对其进行调整。请注意,降低变更数据流的数据保留期限后,所有超过新限额的历史变更数据都将立即且永远无法供该变更数据流的读取方访问。

此数据保留期限需要做出权衡取舍;较长的保留期限对流的数据库产生更大的存储需求。

值捕获类型

变更数据流的值捕获类型配置选项可控制其存储已更改行的值的方式。您可以使用 DDL 为变更数据流指定以下值捕获类型之一:

  • OLD_AND_NEW_VALUES:捕获行的已修改列的旧值和新值。

  • NEW_VALUES:仅捕获非键列的新值,而不捕获旧值。

  • NEW_ROW:每当监控列发生变化时,捕获这些列的所有新值,包括已修改和未修改的值。不会捕获旧值。

  • NEW_ROW_AND_OLD_VALUES:捕获已修改和未修改列的所有新值,以及已修改列的旧值。

排除基于存留时间的删除操作

在 Spanner 中,您可以通过存留时间 (TTL) 设置政策,以定期从 Spanner 表中删除数据。默认情况下,变更数据流包含所有基于 TTL 的删除操作。您可以使用 exclude_ttl_deletes 将变更数据流设置为排除基于 TTL 的删除操作。如果设置此过滤条件以排除基于 TTL 的删除操作,则只有未来基于 TTL 的删除操作才会从变更数据流中排除。

此过滤条件的默认值为 false。如需排除基于 TTL 的删除操作,请将过滤条件设置为 true。您可以在创建变更数据流时添加该过滤条件,也可以修改现有变更数据流以包含该过滤条件

表格修改类型

默认情况下,变更数据流包含所有表修改,例如插入、更新和删除。您可以使用以下可用的过滤条件选项,从变更数据流的范围内过滤上述一项或多项表修改:

  • exclude_insert:排除所有 INSERT 表修改
  • exclude_update:排除所有 UPDATE 表修改
  • exclude_delete:排除所有 DELETE 表修改

这些过滤条件的默认值为 false。如需排除特定类型的表修改,请将过滤条件设置为 true。您可以同时设置一个或多个过滤条件。

创建变更流时,您可以为表修改类型添加过滤条件,也可以针对现有变更流修改表修改类型的过滤条件

读取变更数据流

Spanner 提供多种方式来读取变更数据流的数据:

  • 通过 Dataflow,使用 Apache Beam SpannerIO 连接器。 对于大多数变更流应用,我们建议使用此解决方案。Google 还为常见使用场景提供了 Dataflow 模板。

  • 直接使用 Spanner API。这放弃了 Dataflow 流水线的抽象和功能,以实现最快的速度和灵活性。

  • 通过为 Spanner 变更数据流使用基于 Debezium 的 Kafka 连接器。此连接器会将变更记录直接流式传输到 Kafka 主题中。

您可以使用定向读取为变更数据流读取提供部分隔离。定向读取有助于最大限度地减少对数据库中的事务性工作负载的影响。您可以使用 Spanner API 将更改流读取路由到多区域实例配置或具有可选只读区域的自定义单区域配置中的特定副本类型或区域。如需了解详情,请参阅定向读取

使用 Dataflow

使用 Apache Beam SpannerIO 连接器构建 Dataflow 流水线,以便从变更数据流读取数据。在您使用特定变更数据流的详细信息配置连接器后,它会自动将新的数据变更记录输出到单个无界限 PCollection 数据集,以供 Dataflow 流水线中的后续转换进行进一步处理。

Dataflow 使用数据选取函数将无界限集合划分为逻辑组件或窗口。因此,Dataflow 可提供近乎实时的流式传输,从变更数据流读取数据时,延迟约为 6 秒。

借助 Google 提供的模板,您可以为常见的变更数据流使用场景快速构建 Dataflow 流水线,包括将数据流的所有数据更改发送到 BigQuery 数据集,或将其复制到 Cloud Storage 存储桶

如需更详细地了解变更数据流和 Dataflow 如何协同工作,请参阅使用 Dataflow 构建变更数据流连接

使用 API

除了使用 Dataflow 构建变更数据流流水线之外,您也可以编写使用 Spanner API 直接读取变更数据流记录的代码。这样,您就可以按照与 Spanner 连接器相同的方式读取数据变更记录,消除其提供的抽象作用,换取读取变更数据流数据时尽可能低的延迟时间。

如需了解详情,请参阅查询变更流。如需详细了解如何查询变更数据流和解释返回的记录,请参阅变更数据流分区、记录和查询

使用 Kafka 连接器

Kafka 连接器直接将变更数据流记录输出到 Kafka 主题。您可以不必再使用 Spanner API 查询变更数据流的详细信息。

如需详细了解变更数据流和 Kafka 连接器如何协同工作,请参阅使用 Kafka 连接器构建变更数据流连接

限制

变更数据流有多个限制,包括一个数据库可以拥有的变更数据流数量上限,以及可以监控单个列的数据流数量上限。如需查看完整列表,请参阅更改数据流限制

权限

变更流使用以下参数:

  • 创建、更新或删除变更数据流需要 spanner.databases.updateDdl

  • 读取变更数据流的数据需要 spanner.databases.select

如果使用 SpannerIO 连接器,则读取变更数据流数据的 Dataflow 作业的所有者需要额外的 IAM 权限,可以是应用数据库权限,也可以是单独的元数据数据库权限;请参阅创建元数据数据库

后续步骤