复制的注意事项

本主题介绍在使用 复制组或故障转移组 或者 数据库复制 进行复制时,某些 Snowflake 功能在辅助数据库和对象中的行为,并提供有关使用复制的对象和数据的一般指导。

如果以前已使用 ALTER DATABASE ...ENABLE REPLICATION TO ACCOUNTS 命令为单个数据库启用了数据库复制,请参阅 数据库复制注意事项,以了解特定于数据库复制的其他注意事项。

本主题内容:

复制组和故障转移组的约束

以下各部分说明了将账户对象、数据库和共享添加到复制组和故障转移组时的约束。

数据库和共享对象

以下约束适用于数据库和共享对象:

  • 一个对象只能在一个故障转移组中。

  • 一个对象可以在多个复制组中,只要每个组复制到*不同*的目标账户即可。

  • 一个对象不能同时位于故障转移组和复制组中。

  • 辅助(副本)对象不能添加到主复制组或主故障转移组。

您只能复制出站共享。入站共享 (来自提供商的共享)的复制 受支持。

账户对象

一个账户只能有一个包含数据库或共享 以外 的对象的复制组或故障转移组。

复制权限

本部分介绍可授予角色的复制权限,这些权限指定用户可以对系统中的复制组和故障转移组对象执行的操作。有关 GRANT 命令的语法,请参阅 GRANT <privileges>

备注

对于:doc:数据库复制 </user-guide/db-replication-config>,只有具有 ACCOUNTADMIN 角色的用户才能启用和管理数据库复制与故障转移。有关数据库复制所需权限的其他信息,请参阅 第 6 步:按计划刷新辅助数据库 中的 所需权限表

权限

对象

用途

备注

OWNERSHIP

复制组

故障转移组

授予删除、更改和授予或撤销对象访问权限的能力。

可由以下角色授予:

ACCOUNTADMIN 角色

具有 MANAGE GRANTS 权限的角色

具有组的 OWNERSHIP 权限的角色。

CREATE REPLICATION GROUP

账户

授予创建复制组的能力。

必须由 ACCOUNTADMIN 角色授予。

CREATE FAILOVER GROUP

账户

授予创建故障转移组的能力。

必须由 ACCOUNTADMIN 角色授予。

FAILOVER

故障转移组

授予将辅助故障转移组提升为主故障转移组的能力。

可以由具有组的 OWNERSHIP 权限的角色授予或撤销。

REPLICATE

复制组

故障转移组

授予刷新辅助组的能力。

可以由具有组的 OWNERSHIP 权限的角色授予或撤销。

MODIFY

复制组

故障转移组

授予更改对象的设置或属性的能力。

可以由具有组的 OWNERSHIP 权限的角色授予或撤销。

MONITOR

复制组

故障转移组

授予查看对象内详细信息的能力。

可以由具有组的 OWNERSHIP 权限的角色授予或撤销。

有关创建具有指定权限集的自定义角色的说明,请参阅 创建自定义角色

有关对 安全对象 执行 SQL 操作的相应角色和权限授予的一般信息,请参阅 访问控制概述

跨复制组的复制和引用

在某些情况下,复制(或故障转移)组中具有悬空引用(即对其他复制或故障转移组中的对象的引用)的对象可能会成功复制到目标账户。如果复制操作导致目标账户中的行为与源账户中可能发生的行为一致,则复制取得成功。

例如,如果故障转移组 fg_a 中的表内的列引用故障转移组 fg_b 中的序列,则两个组的复制都将成功。如果在复制 fg_b 之前 复制了 fg_a,那么,如果未复制 fg_b,则引用该序列的表上的插入操作(在故障转移后)将会 失败。此行为可能发生在源账户中。如果在源账户中删除了序列,而某个表的列引用了被删除的该序列,则此表上的插入操作将会失败。

当悬空引用用作保护数据的安全策略时,必须 先复制具有该安全策略的复制(或故障转移)组,然后才能复制包含了引用该策略的对象的任何复制组。

注意

如果更新用于保护单独复制组或故障转移组中的数据的安全策略,则可能会导致不一致,因此应谨慎进行此类更新。

对于数据库对象,您可以在 Account Usage OBJECT_DEPENDENCIES 视图 中查看 对象相关性

悬空引用和网络策略

网络策略中的悬空引用可能会导致复制失败,并显示以下错误消息:

Dangling references in the snapshot. Correct the errors before refreshing again.
The following references are missing (referred entity <- [referring entities])

为避免悬空引用,请在对复制组或故障转移组执行 CREATE 或 ALTER 命令时,在 OBJECT_TYPES 列表中指定以下对象类型:

  • 如果网络策略使用网络规则,请将包含用于创建网络规则的架构的数据库包括在内。

  • 如果网络策略与账户关联,请在 OBJECT_TYPES 列表中包含 NETWORK POLICIESACCOUNT PARAMETERS

  • 如果网络策略与用户关联,请在 OBJECT_TYPES 列表中包含 NETWORK POLICIESUSERS

有关更多详细信息,请参阅 复制网络策略

悬空引用和包策略

如果账户中设置了 包策略,则在对包含账户对象的复制或故障转移组执行刷新操作期间,将发生以下悬空引用错误:

003131 (55000): Dangling references in the snapshot. Correct the errors before refreshing again.
The following references are missing (referred entity <- [referring entities]):
POLICY '<policy_db>.<policy_schema>.<packages_policy_name>' <- [ACCOUNT '<account_locator>']

为避免悬空引用,请将包含包策略的数据库复制到目标账户。包含策略的数据库可以位于相同或不同的复制或故障转移组中。

悬空引用和密钥

有关详细信息,请参阅 复制和密钥

悬空引用和流

流的悬空引用会导致复制失败,并显示以下错误消息:

Primary database: the source object ''<object_name>'' for this stream ''<stream_name>'' is not included in the replication group.
Stream replication does not support replication across databases in different replication groups. Please see Streams Documentation
https://docs.snowflake.com/en/user-guide/account-replication-considerations#replication-and-streams for options.

要避免悬空引用错误,请执行以下步骤:

  • 主数据库必须包含流及其基对象,或者

  • 以下数据库必须包含在同一复制组或故障转移组中:包含流的数据库,以及包含流引用的基对象的数据库。

复制与只读辅助对象

目标账户中的所有辅助对象(包括辅助数据库和共享)都是只读的。无法在目标账户中以本地方式更改复制的对象或对象类型。例如,如果 USERS 对象类型从源账户复制到目标账户,则无法在目标账户中创建或修改新用户。

在目标账户中,可以*创建和修改新的本地数据库和共享。如果 :code:`ROLES` 也复制到目标账户,则无法在该目标账户中创建或修改新角色。因此,无法向目标账户中的辅助对象上的角色授予权限或撤销其权限。但是,*可以 向在目标账户中创建的本地对象(例如,数据库、共享或者复制组或故障转移组)上的辅助角色授予权限或撤销其权限。

目标账户中的复制和对象

如果您在目标账户中通过 *复制以外的任何方式*(例如使用脚本)创建了账户对象(例如用户和角色),则这些用户和角色默认情况下没有全局标识符。当从源账户刷新目标账户时,刷新操作会从目标账户中**删除**属于以下类型的所有账户对象:OBJECT_TYPES 列表中的没有全局标识符的类型。

备注

用于复制 USERS 或 ROLES 的初始刷新操作可能会导致错误。这有助于防止意外删除与用户和角色关联的数据和元数据。有关确定是删除这些对象类型还是刷新操作失败的情况的更多信息,请参阅 用户和角色的初始复制

为避免删除这些对象,请参阅 将全局 IDs 应用于目标账户中通过脚本创建的对象

在目标账户中重新创建的对象

如果使用 CREATE OR REPLACE 语句替换源账户中的现有对象,则会删除现有对象,然后在单个事务中创建具有相同名称的新对象。例如,如果对现有表 t1 执行 CREATE OR REPLACE 语句,则会删除表 t1,然后创建新表 t1。有关更多信息,请参阅 CREATE TABLE 使用说明

当替换目标账户上的对象时,DROP 和 CREATE 语句不会在刷新操作期间自动执行。这意味着在将对象重新创建为新对象时,该对象可能会短暂地从目标账户中消失。

复制与安全策略

可以使用复制组和故障转移组来复制包含安全策略和引用(即分配)的数据库。安全策略包括:

如果使用 数据库复制,请参阅 数据库复制和安全对象

身份验证、密码和会话策略

在复制组或故障转移组中指定了包含策略 (ALLOWED_DATABASES = policy_db) 和 USERS 的数据库时,系统会复制用户的身份验证、密码和会话策略引用。

如果策略数据库或用户已复制到目标账户,请更新源账户中的复制组或故障转移组,以包含成功复制策略所需的数据库和对象类型。然后,执行刷新操作以更新目标账户。

如果未使用用户级策略,则不需要将 USERS 包含在复制组或故障转移组中。

备注

策略必须与账户级策略分配和用户级策略分配位于同一账户中。

如果对账户或账户中的用户设置了安全策略,并且未更新复制组或故障转移组以将包含该策略和 USERSpolicy_db 包括在内,则目标账户中会发生悬空引用。在这种情况下,悬空引用意味着 Snowflake 无法在目标账户中找到策略,因为策略的完全限定名称指向源账户中的数据库。因此,目标账户或目标账户中的用户不需要遵守安全策略。

要成功复制安全策略,请验证复制组或故障转移组是否包含了防止悬空引用所需的对象类型和数据库。

复制和密钥

您只能使用复制或故障转移组复制密钥。在单个复制组或故障转移组中指定包含密钥的数据库,包含引用密钥的 UDFs 或存储过程的数据库以及引用密钥的集成。

如果在一个复制组或故障转移组中有包含密钥的数据库,而在另一个复制组或故障转移组中有引用密钥的集成:

  • 如果先复制集成,然后再复制密钥,那么操作就会成功:所有对象都被复制,而且没有悬挂引用。

  • 如果在集成前复制了密钥,而目标账户中尚不存在该密钥,则会在目标账户中添加“占位符密钥”,以防止悬空引用。Snowflake 会将占位符密钥映射到集成。

    复制包含集成的组后,在对包含密钥的组执行下一次刷新操作时,Snowflake 会更新目标账户,以将占位符密钥替换为集成中引用的密钥。

  • 如果复制密钥,但没有将集成从 account1 复制到 account2,则集成在目标账户 (account2) 中不起作用,因为没有可使用密钥的集成。此外,如果进行故障转移,并且将目标账户提升为源账户,则集成将不起作用。

    当您决定进行故障转移以将 account1 作为源账户时,密钥和集成引用匹配,并且不会使用占位符密钥。这样就可以使用安全集成和包含凭据的密钥,因为对象可以相互引用。

复制和克隆

克隆的对象以物理方式而不是逻辑方式复制到辅助数据库。也就是说,标准数据库中的克隆表不会占用总体数据存储容量,除非或直到对克隆执行的 DML 操作增加或修改现有数据。但是,当克隆表复制到辅助数据库时,物理数据也会复制,从而增大账户的数据存储使用量。

复制与自动聚类

在主数据库中,Snowflake 使用 自动聚类 对聚类的表进行监控,并根据需要将这些表重聚类。作为刷新操作的一部分,聚类的表按照表微分区的当前排序复制到辅助数据库。因此,不会 对辅助数据库中的聚类表再次执行重聚类(这是多余的)。

如果辅助数据库包含聚类的表,并且该数据库被提升为主数据库,Snowflake 会开始对该数据库中的表进行自动聚类,同时暂停监控先前的主数据库中的聚类表。

有关物化视图自动聚类的信息,请参阅本主题中的 复制和物化视图

复制与频繁变动的大型表

当更新或删除表的一行或多行时,系统会重新创建在主数据库中存储这些数据的所有受影响的微分区,而且,这些微分区必须同步到辅助数据库。对于频繁变动的大型维度表,复制成本可能很高。

对于会产生很高复制成本的频繁变动的大型维度表,可以采取以下缓解措施:

  • 以较低的频率复制任何存储此类表的主数据库。

  • 更改数据模型以减少变动。

有关更多信息,请参阅 管理大型、高流失表的成本

复制与 Time Travel

Time Travel故障安全 数据是为辅助数据库独立维护的,不会从主数据库复制。使用 Time Travel 查询辅助数据库中的表和视图时,结果可能会与在主数据库中执行同一查询时不同。

历史数据:

使用 Time Travel 时,可用于在主数据库中进行查询的历史数据不会复制到辅助数据库。

例如,假设使用 Snowpipe 每 10 分钟将数据连续加载到表中,并且每小时刷新一次辅助数据库。刷新操作只复制表的最新版本。虽然保留时间窗口内每小时的表版本都可用于通过 Time Travel 进行查询,但每小时内的迭代版本(单个 Snowpipe 加载)都不可用。

数据保留期:

在通过写入到主数据库中的表的 DML 操作(即更改或删除数据)来刷新辅助数据库时,辅助数据库中的表的数据保留期便开始。

备注

数据保留期参数 DATA_RETENTION_TIME_IN_DAYS 仅复制到辅助数据库中的数据库对象,而不复制到数据库本身。有关参数复制的更多详细信息,请参阅 参数

复制和物化视图

在主数据库中,Snowflake 执行物化视图的自动后台维护。当基表发生更改时,在该表上定义的所有物化视图都将由后台服务更新,该后台服务使用 Snowflake 提供的计算资源。此外,如果为物化视图启用了自动聚类,则系统会监控该视图,并根据需要在主数据库中将该视图重聚类。

刷新操作会将物化视图 定义 复制到辅助数据库,但不会复制物化视图 数据。默认情况下,系统会启用辅助数据库中物化视图的自动后台维护。如果为主数据库中的物化视图启用了自动聚类,则也将启用辅助数据库中的物化视图自动监控和重聚类。

备注

物化视图的自动后台同步的费用记入到包含辅助数据库的每个账户。

复制和动态表

根据包含动态表的主数据库是在复制组中复制还是在故障转移组中复制,动态表复制的行为会有所不同。

动态表和复制组

可以使用复制组复制包含动态表的数据库。该数据库依赖的基对象不需要在同一个复制组中。

辅助对象在目标账户中是 只读 的。如果在目标账户中删除辅助复制组,则该组中包含的数据库会变为可读写。但是,即使在目标账户中删除了辅助组,复制组中包含的任何动态表都仍 保持 只读状态。在这些只读动态表上,不能执行 DML 或动态表刷新。

动态表和故障转移组以及数据库复制

可以使用故障转移组复制包含动态表的数据库。该数据库依赖的基对象*必须*包含在同一个故障转移组中。否则,在刷新操作进行期间会出现悬空引用,并显示以下错误消息:

002749 (55000): SQL execution error: Dynamic table <dt_name> has dependencies that are missing in the replication membership: <dependency_table_name>

如果使用数据库复制将动态表复制到数据库中,同样会发生此情况。动态表依赖的基对象必须包含在同一个数据库中,以避免出现悬空引用错误。

辅助动态表是只读的,不会刷新。发生故障转移并将辅助动态表提升为主动态表后,如果动态表配置为增量刷新数据,则第一次刷新是重新初始化,然后是增量刷新。

复制和 Snowpipe 流

由主数据库中的 Snowpipe Streaming 填充的表会复制到目标账户中的辅助数据库。

在主数据库中,系统会创建表,并通过 通道 插入行。偏移令牌 会跟踪引入进度。刷新操作会将表对象、表数据以及与表关联的通道偏移从主数据库复制到辅助数据库。

  • 用于检索偏移的 Snowflake Streaming 只读操作在源账户和目标账户中均可用:

    • 通道 getLatestCommittedOffsetToken (https://javadoc.io/doc/net.snowflake/snowflake-ingest-sdk/latest/net/snowflake/ingest/streaming/SnowflakeStreamingIngestChannel.html#getLatestCommittedOffsetToken()) API

    • SHOW CHANNELS 命令

  • Snowflake Streaming 写入操作仅在源账户中可用:

    • 客户端 openChannel (https://javadoc.io/doc/net.snowflake/snowflake-ingest-sdk/latest/net/snowflake/ingest/streaming/SnowflakeStreamingIngestClient.html#openChannel(net.snowflake.ingest.streaming.OpenChannelRequest)) API

    • 通道 insertRow (https://javadoc.io/doc/net.snowflake/snowflake-ingest-sdk/latest/net/snowflake/ingest/streaming/SnowflakeStreamingIngestChannel.html#insertRow(java.util.Map,java.lang.String)) API

    • 通道 insertRows (https://javadoc.io/doc/net.snowflake/snowflake-ingest-sdk/latest/net/snowflake/ingest/streaming/SnowflakeStreamingIngestChannel.html#insertRows(java.lang.Iterable,java.lang.String)) API

避免数据丢失

为了避免故障转移时丢失数据,在上游数据源中成功插入的行的数据保留时间必须大于配置的 复制计划。如果将数据插入到主数据库的表中,并且在可以将数据复制到辅助数据库之前发生故障转移,则需要将相同的数据插入到新提升的主数据库的表中。以下是示例场景:

  1. 主数据库 repl_db 中的表 t1 使用 Snowpipe Streaming 和 Kafka Connector 来填充数据。

  2. 在*主*数据库中,通道 1 的 offsetToken 为 100,通道 2 的 t1 为 100。

  3. 刷新操作在目标账户中成功完成。

  4. 在*辅助*数据库中,通道 1 的 offsetToken 为 100,通道 2 的 t1 为 100。

  5. 在主数据库中,将更多行插入到 t1

  6. 现在,在*主*数据库中,通道 1 的 offsetToken 为 200,通道 2 的 t1 为 200。

  7. 故障转移发生在可以将其他行和新的通道偏移复制到辅助数据库之前。

在本例中,在新提升的主数据库中,表 t1 的每个通道中缺少 100 个偏移。要插入缺失的数据,请参阅 在新提升的源账户中重新打开 Snowpipe Streaming 的活动通道

要求

要支持 Snowpipe Streaming 复制,需要以下最低版本:

  • Snowflake Ingest SDK 版本 1.1.1 及更高版本

  • 如果使用 Kafka Connector:Kafka Connector 版本 1.9.3 及更高版本

在上游数据源中成功插入的行的数据保留时间必须大于配置的复制计划。如果您正在使用 Kafka Connector,请确保您的 log.retention 配置设置了足够的缓冲区。

复制和暂存区

以下约束适用于暂存区对象:

  • Snowflake 目前支持将暂存区复制作为基于组的复制(复制组和故障转移组)的一部分。数据库复制不支持暂存区复制。

  • 可以复制一个外部暂存区。但是,系统不会复制外部暂存区上的文件。

  • 可以复制一个内部暂存区。要复制内部暂存区上的文件,必须在该暂存区上启用目录表。Snowflake 只复制目录表映射的文件。

  • 当您复制具有目录表的内部暂存区时,不能在主暂存区或辅助暂存区上禁用该目录表。目录表包含有关复制的文件和使用 COPY 语句加载的文件的重要信息。

  • 如果内部暂存区上的目录表包含大于 5GB 的文件,则刷新操作将失败。要解决此限制,请将所有大于 5GB 的文件移至其他暂存区。

    您无法在主要暂存区或辅助暂存区,或以前已复制的任何暂存区上禁用目录表。在将包含暂存区的数据库添加到复制或故障转移组 之前,请执行以下步骤。

    1. 在主要暂存区 禁用目录表

    2. 将大于 5GB 的文件移动到未启用目录表的另一个暂存区。

    3. 将文件移动到另一个暂存区后,请在主要暂存区上重新启用目录表。

  • 系统不会复制用户暂存区和表暂存区上的文件。

  • 对于使用存储集成的已命名外部暂存区,您必须在故障转移之前在目标账户中为辅助存储集成配置信任关系。有关更多信息,请参阅 配置辅助存储集成的云存储访问权限

  • 如果您复制具有目录表的外部暂存区,并且已为源目录表配置了 自动刷新,则必须在故障转移之前为 辅助 目录表配置自动刷新。有关更多信息,请参阅 配置目录表在辅助暂存区的自动刷新

  • 如果已复制暂存区上的目录表与该暂存区上的已复制文件不一致,则复制命令的执行时间可能会比预期的长。若要使目录表保持一致,请使用 ALTER STAGE ... REFRESH</sql-reference/sql/alter-stage> 语句。要检查目录表的一致性状态,请使用 SYSTEM$GET_DIRECTORY_TABLE_STATUS 函数。

复制和管道

以下约束适用于管道对象:

  • Snowflake 目前支持将管道复制作为基于组的复制(复制组和故障转移组)的一部分。数据库复制不支持管道复制。

  • 仅在管道与其目标表属于同一复制组时,Snowflake 才会复制管道的复制历史记录。

  • 不支持复制通知集成。

  • Snowflake 仅在最新的表截断后复制加载历史记录。

  • 要接收通知,必须 在故障转移之前 在目标账户中配置辅助自动引入管道。有关更多信息,请参阅 配置辅助自动引入管道的通知

  • 使用 SYSTEM$PIPE_STATUS 函数,解决故障转移后未处于预期执行状态的任何管道。

数据指标函数的复制 (DMFs)

以下行为适用于 DMF 复制:

事件表

存储手动调用或安排 DMF 运行的结果的事件表不会被复制,因为事件表是 Snowflake 账户的本地表,而 Snowflake 不支持复制事件表。

复制组

当您将包含 DMFs 的数据库添加到复制组时,目标账户中将发生以下情况:

  • DMFs 从源账户复制。

  • DMF 定义 指定的表或视图(例如使用 外键引用)将从源账户复制,除非该表或视图与 Cross-Cloud Auto-Fulfillment 关联。

  • 计划的 DMFs 在目标账户中被暂停。当您将目标账户提升为源账户时,辅助 DMFs 将恢复其计划,并且辅助 DMFs 将成为主要 DMFs。

故障转移组

使用故障转移组复制包含 DMFs 的数据库时,在发生故障转移时将发生以下情况:

  • 当您将目标账户提升为源账户时,恢复暂停的 DMFs 计划。

  • 在将其他账户提升为源账户后,在目标账户中暂停计划的 DMFs。

如果不将包含 DMF 的数据库复制到目标账户,则当目标账户提升为源账户时,与表或视图的 DMF 关联将被 删除,因为它们在新提升的源账户中不可用。

小技巧

在对账户进行故障转移之前,通过调用 DATA_METRIC_FUNCTION_REFERENCES Information Schema 表函数来 检查 DMF 引用,以在提升和刷新操作之前确定与 DMF 相关联的表对象。

存储过程和用户定义函数 (UDFs) 的复制

存储过程和 UDFs 从主数据库复制到辅助数据库。

存储过程和 UDFs 以及暂存区

如果存储过程或 UDF 依赖于暂存区中的文件(例如,如果在从暂存区上传的 Python 代码中定义了存储过程),则必须将暂存区及其文件复制到辅助数据库。有关复制暂存区的更多信息,请参阅 暂存区、管道和加载历史记录复制

例如,如果主数据库具有内联的 Python UDF (其导入在暂存区中存储的任何代码),则除非在辅助数据库中复制暂存区及其导入的代码,否则该 UDF 将无法工作。

存储过程和 UDFs 以及外部网络访问

如果存储过程或 UDF 依赖于对 外部网络位置 的访问,则必须复制以下对象:

  • EXTERNAL ACCESS INTEGRATIONS 必须包含在复制组或故障转移组的 allowed_integration_types 列表中。

  • 包含网络规则的数据库。

  • 包含密钥的数据库,该密钥存储用于与外部网络位置进行身份验证的凭据。

  • 如果密钥对象引用安全集成,则必须将 SECURITY INTEGRATIONS 包括在复制组或故障转移组的 allowed_integration_types 列表中。

复制和流

本部分介绍在进行以下操作时的建议做法和潜在关注领域:在 跨多个账户复制数据库账户复制和故障转移/故障恢复 中复制流。

流支持的源对象

复制的流可以成功地跟踪同一数据库中的表和视图的更改数据。

当前,以下源对象类型 受支持:

  • 外部表

  • 数据库中的表或视图与流数据库分开,除非流数据库和存储源对象的数据库 包含在同一个 复制组或故障转移组中

  • 共享数据库(即从提供商账户共享到您账户的数据库)中的表或视图

启用 暂存区、管道和加载历史记录复制 后,支持复制目录表上的流。

如果主数据库包含带有不支持的源对象的流,则数据库复制或刷新操作将失败。如果任何流的源对象已被删除,则该操作也会失败。

复制的源对象不支持仅追加流。

避免数据重复

备注

除了本部分中描述的场景之外,辅助数据库中的流在第一次包含在刷新操作中时,可能会返回重复的行。在这种情况下,*重复的行*是指一行中有多个 METADATA&ACTION 列值。

执行初始刷新操作之后,在辅助数据库中应该不会遇到此特定问题。

当 DML 操作多次从流中写入相同的更改数据,但不进行唯一性检查时,就会发生数据重复。如果流和流更改数据的目标表存储在不同的数据库中,并且这些数据库未在同一组中进行复制和故障转移,则可能会发生数据重复。

例如,假设您定期将更改数据从流 s 插入到表 dt 中。(在此示例中,流的源对象并不重要。)流和目标表存储在不同的数据库中。

  1. 在时间戳 t1 处,在流 s 的源表中插入一行,并创建一个新的表版本。流存储此表版本的偏移。

  2. 在时间戳 t2 处,刷新存储流的辅助数据库。复制的流 s 现在存储偏移。

  3. 在时间戳 t3 处,在表 dt 中插入流 s 的更改数据。

  4. 在时间戳 t4 处,存储流 s 的辅助数据库进行故障转移。

  5. 在时间戳 t5 处,在表 dt 中再次插入流 s 的更改数据。

要避免这种情况,请复制并故障转移存储流及其目标表的数据库。

任务 WHEN 子句中的流引用

为避免在运行复制的任务(其在 WHEN boolean_expr 子句中引用流)时出现意外行为,建议您执行以下操作之一:

  • 在同一数据库中创建任务和流,或者

  • 如果存储流的数据库不同于引用流的任务所在的数据库,请将这两个数据库包含在同一 故障转移组 中。

如果任务引用另一个数据库中的流,并且两个数据库未包含在同一故障转移组中,则无需使用包含流的数据库,也可将包含该任务的数据库进行故障转移。在这种情况下,当在故障转移的数据库中恢复该任务时,它会在尝试运行时记录错误,并且无法找到引用的流。要解决此问题,可以将包含流的数据库进行故障转移,或者,在与包含该任务的故障转移数据库相同的账户中重新创建数据库和流。

流过时

如果主数据库中的流已 过时,则辅助数据库中的复制流也会过时,并且无法查询该流或使用其更改数据。若要解决此问题,请在主数据库中重新创建流(使用 CREATE OR REPLACE STREAM)。刷新辅助数据库后,复制的流将重新变为可读。

请注意,默认情况下,重新创建的流的偏移是当前表版本。您可以使用 Time Travel 重新创建指向早期表版本的流,但是,复制的流将保持不可读状态。有关更多信息,请参阅本主题中的 流复制和 Time Travel

流复制和 Time Travel

在将主数据库进行故障转移后,如果数据库中的流使用 Time Travel 读取上次刷新时间戳之前的某个时间点的源对象 表版本,则将无法查询复制的流或使用更改数据。同样,使用 SELECT 语句的 CHANGES 子句查询上次刷新时间戳之前的某个时间点的源对象更改数据也会失败,并会返回错误。

这是因为刷新操作会将表历史记录折叠成单个表版本。在刷新操作时间戳之前创建的迭代表版本不会保留在复制的源对象的表历史记录中。

请参考以下示例:

流复制和 Time Travel
  1. 在启用了更改跟踪的主数据库中创建表 t1``(表版本为 ``tv0)。后续 DML 事务创建表版本 tv1tv2

  2. 刷新包含表 t1 的辅助数据库。此复制表的表版本为 tv2,但是不复制表历史记录。

  3. 在主数据库中创建一个流,并使用 Time Travel 将其偏移设置为表版本 tv1

  4. 辅助数据库进行故障转移,成为主数据库。

  5. 查询流 s1 返回错误,因为表版本 tv1 不在表历史记录中。

请注意,当表 t1 上的后续 DML 事务将表版本迭代到 tv3 时,流 s1 的偏移会推前。流重新变为可读。

避免数据丢失

如果辅助数据库的最近一次刷新操作在故障转移操作之前未完成,则可能会发生数据丢失。建议您经常刷新辅助数据库,以尽量降低风险。

复制和任务

本部分介绍 跨多个账户复制数据库账户复制和故障转移/故障恢复 中的任务复制。

复制场景

下表描述了不同的任务场景,并指定是否复制任务。除非另有说明,否则这些场景与独立任务和 任务图 中的任务都相关:

场景

复制

备注

任务已创建,并已恢复或手动执行(使用 EXECUTE TASK)。恢复或执行任务将创建初始任务版本。

任务已创建,但从未恢复或执行。

已重新创建任务(使用 CREATE OR REPLACE TASK),但从未恢复或执行。

复制重新创建任务 之前 的最新版本。

恢复或手动执行任务将提交新版本。当再次复制数据库时,新的或最新的版本将复制到辅助数据库。

任务已创建并恢复或执行,随后被修改(使用 ALTER TASK),但未再次恢复或执行。

恢复或手动执行任务将提交新版本,其中包含对任务参数的任何更改。由于从未提交新更改,因此将复制暂停和修改任务之前的最新版本。

请注意,如果在保留期(当前为 30 天)内未恢复修改的任务,则将删除任务的最新版本。在保留期之后,任务不会复制到辅助数据库(除非再次恢复)。

独立任务已创建并恢复或执行,但随后被删除。

任务图表中的根任务已创建并恢复或执行,但随后被暂停并删除。

不会将整个任务图表复制到辅助数据库。

任务图表中的子任务已创建并恢复或执行,但随后被暂停并删除。

任务图表的最新版本(在暂停并删除任务之前)复制到辅助数据库。

已复制任务的恢复或暂停状态

如果满足以下所有条件,则任务将在恢复状态下复制到辅助数据库:

  • 当复制或刷新操作开始后,独立任务或根任务在主数据库中处于恢复状态,直到操作完成为止。如果任务仅在此期间的一部分时间内处于恢复状态,则仍可能在恢复状态下复制该任务。

    子任务在任务的最新版本中处于恢复状态。

  • 父数据库已与相同或不同 复制组或故障转移组 中的角色对象一起复制到目标账户。

    复制角色和数据库后,必须通过分别执行以下命令之一来刷新目标账户中的对象:ALTER REPLICATION GROUP ...REFRESHALTER FAILOVER GROUP ...REFRESH。如果通过执行 ALTER DATABASE ...REFRESH 来刷新数据库,则数据库中的任务状态将更改为已暂停。

    复制或刷新操作会将在提交最新表版本时为当前任务授予的权限包括在内。有关更多信息,请参阅本主题中的 复制的任务和权限授予

如果不满足这些条件,则任务将在暂停状态下复制到辅助数据库。

备注

辅助任务在故障转移之后才会进行计划,无论其 state 如何。有关更多详细信息,请参阅 在故障转移后运行任务

复制的任务和权限授予

如果将父数据库与相同或不同复制组或故障转移组中的角色对象一起复制到目标账户,则也会复制对数据库中的任务授予的权限。

以下逻辑确定在复制或刷新操作中复制哪些任务权限:

  • 如果当前任务所有者(即对任务具有 OWNERSHIP 权限的角色)与上次恢复任务时的角色相同,则将任务的所有当前授权复制到辅助数据库。

  • 如果当前任务所有者与上次恢复任务时的角色 同,则仅将任务版本中授予所有者角色的 OWNERSHIP 权限复制到辅助数据库。

  • 如果当前任务所有者角色不可用(例如,子任务被删除,但任务图表的新版本尚未提交),则仅将任务版本中授予所有者角色的 OWNERSHIP 权限复制到辅助数据库。

在故障转移后运行任务

将辅助故障转移组提升为主组后,会逐步安排运行故障转移组内数据库中的任何已恢复任务。恢复所有已恢复的独立任务和任务图表的正常安排所需的时间取决于数据库中已恢复的任务数。

复制和标签

标签及其分配可以从源账户复制到目标账户。

从源账户进行初始复制后,无法在目标账户中修改标签分配。例如,不允许在辅助(即复制的)数据库上设置标签。要在目标账户中修改标签分配,请在源账户中修改这些分配,然后将它们复制到目标账户。

要成功复制标签,请确保复制组或故障转移组包含:

  • ALLOWED_DATABASES 属性中包含标签的数据库。

  • OBJECT_TYPES 属性中具有标签的其他账户级对象,例如 ROLESWAREHOUSES

    有关更多信息,请参阅 CREATE REPLICATION GROUPCREATE FAILOVER GROUP

历史使用情况数据

主数据库中的活动历史使用情况数据不会复制到辅助数据库。每个账户都有自己的查询历史记录、登录历史记录等。

历史使用情况数据包括以下 Snowflake Information Schema 表函数或 Account Usage 视图返回的查询数据:

  • COPY_HISTORY

  • LOGIN_HISTORY

  • QUERY_HISTORY

语言: 中文