在 Amazon Aurora MySQL 数据库集群中使用本地写入转发 - Amazon Aurora
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

在 Amazon Aurora MySQL 数据库集群中使用本地写入转发

本地(集群内)写入转发支持您的应用程序直接在 Aurora 副本上发出读/写事务。然后,这些事务转发到写入器数据库实例进行提交。当您的应用程序要求先写后读一致性(即能够读取事务中的最新写入内容)时,您可以使用本地写入转发。

只读副本从写入器异步接收更新。如果不进行写入转发,则必须在写入器数据库实例上处理任何要求先写后读一致性的读取。或者,您必须开发复杂的自定义应用程序逻辑,以利用多个只读副本来实现可扩展性。您的应用程序必须完全拆分所有读取和写入流量,保持两组数据库连接才能将流量发送到正确的端点。当查询是应用程序内单个逻辑会话或事务的一部分时,这种开发开销会使应用程序设计复杂化。此外,由于不同只读副本的复制滞后可能不同,因此很难在数据库中的所有实例之间实现全局读取一致性。

写入转发避免了拆分这些事务或将它们专门发送给写入器的必要性,从而简化了应用程序开发。对于需要读取事务中最新写入内容且对写入延迟不敏感的工作负载,通过这项新功能可以轻松实现读取扩展。

本地写入转发与全局写入转发不同,后者将写入从辅助数据库集群转发到 Aurora 全局数据库中的主数据库集群。您可以在属于 Aurora 全局数据库的数据库集群中使用本地写入转发。有关更多信息,请参阅在 Amazon Aurora Global Database 中使用写入转发

本地写入转发需要 Aurora MySQL 版本 3.04 或更高版本。

启用本地写入转发

原定设置情况下,Aurora MySQL 数据库集群不启用本地写入转发。您在集群级别而不是在实例级别启用本地写入转发。

重要

您还可以为使用二进制日志记录的跨区域只读副本启用本地写入转发,但写入操作不会转发到源 Amazon Web Services 区域。它们会被转发到二进制日志只读副本集群的写入器数据库实例。

仅当您有写入辅助 Amazon Web Services 区域中的二进制日志只读副本的应用场景时,才使用此方法。否则,最后可能会出现“分裂大脑”的情况,即复制的数据集彼此不一致。

除非绝对必要,否则我们建议您对全局数据库使用全局写入转发,而不是对跨区域只读副本使用本地写入转发。有关更多信息,请参阅在 Amazon Aurora Global Database 中使用写入转发

使用 Amazon Web Services Management Console,在创建或修改数据库集群时,选中只读副本写入转发下的开启本地写入转发复选框。

要使用 Amazon CLI 启用写入转发,请使用 --enable-local-write-forwarding 选项。当您使用 create-db-cluster 命令创建新的数据库集群时,此选项将起作用。当您使用 modify-db-cluster 命令修改现有数据库集群时,它也起作用。您可以结合这些相同的 CLI 命令使用 --no-enable-local-write-forwarding 选项来禁用写入转发。

以下示例创建了一个启用写入转发的 Aurora MySQL 数据库集群。

aws rds create-db-cluster \ --db-cluster-identifier write-forwarding-test-cluster \ --enable-local-write-forwarding \ --engine aurora-mysql \ --engine-version 8.0.mysql_aurora.3.04.0 \ --master-username myuser \ --master-user-password mypassword \ --backup-retention 1

然后,您可以创建写入器和读取器数据库实例,以便您可以使用写入转发。有关更多信息,请参阅创建 Amazon Aurora 数据库集群

要使用 Amazon RDS API 启用写入转发,请将 EnableLocalWriteForwarding 参数设置为 true。当您使用 CreateDBCluster 操作创建新的数据库集群时,此参数起作用。当您使用 ModifyDBCluster 操作修改现有数据库集群时,它也起作用。您可以通过将 EnableLocalWriteForwarding 参数设置为 false 来禁用写入转发。

为数据库会话启用写入转发

aurora_replica_read_consistency 参数是启用写入转发的数据库参数和数据库集群参数。您可以为读取一致性级别指定 EVENTUALSESSIONGLOBAL。要了解有关一致性级别的更多信息,请参阅写入转发的读取一致性

以下规则适用于此参数:

  • 原定设置值为 ''(null)。

  • 仅当您将 aurora_replica_read_consistency 设置为 EVENTUALSESSIONGLOBAL 时,写入转发才可用。此参数仅适用于启用了写入转发的数据库集群的读取器实例。

  • 您不能在多语句事务内设置此参数(如果为空)或取消其设置(如果已设置)。在此类事务中,您可以将其从一个有效值更改为另一个有效值,但我们不建议执行此操作。

检查数据库集群是否启用了写入转发

要确定是否可以在数据库集群中使用写入转发,请确认该集群的属性 LocalWriteForwardingStatus 是否设置为 enabled

在 Amazon Web Services Management Console中,在集群详细信息页面的配置选项卡上,您可以看到本地只读副本写入转发的状态为已启用

要查看所有集群的写入转发设置的状态,请运行以下 Amazon CLI 命令。

aws rds describe-db-clusters \ --query '*[].{DBClusterIdentifier:DBClusterIdentifier,LocalWriteForwardingStatus:LocalWriteForwardingStatus}' [ { "LocalWriteForwardingStatus": "enabled", "DBClusterIdentifier": "write-forwarding-test-cluster-1" }, { "LocalWriteForwardingStatus": "disabled", "DBClusterIdentifier": "write-forwarding-test-cluster-2" }, { "LocalWriteForwardingStatus": "requested", "DBClusterIdentifier": "test-global-cluster-2" }, { "LocalWriteForwardingStatus": "null", "DBClusterIdentifier": "aurora-mysql-v2-cluster" } ]

对于 LocalWriteForwardingStatus,数据库集群可以具有以下值:

  • disabled – 写入转发已禁用。

  • disabling – 正在禁用写入转发。

  • enabled – 写入转发已启用。

  • enabling – 正在启用写入转发。

  • null – 写入转发不适用于此数据库集群。

  • requested – 已请求写入转发,但尚未激活。

应用程序和 SQL 与写入转发的兼容性

您可以将以下类型的 SQL 语句与写入转发一起使用:

  • 数据操作语言 (DML) 语句,如 INSERTDELETEUPDATE。对于您可以与写入转发一起使用的这些语句的属性存在一些限制,如下所述。

  • SELECT ... LOCK IN SHARE MODESELECT FOR UPDATE 语句。

  • PREPAREEXECUTE 语句。

在具有写入转发功能的数据库集群中使用某些语句时,不允许这些语句,否则它们可能产生过时的结果。因此,原定设置情况下,数据库集群的 EnableLocalWriteForwarding 设置处于禁用状态。在启用该设置之前,请检查以确保您的应用程序代码不受任何这些限制的影响。

以下限制适用于与写入转发一起使用的 SQL 语句。在某些情况下,您可以在启用了写入转发的数据库集群上使用这些语句。如果 aurora_replica_read_consistency 配置参数未在会话中启用写入转发,则此方法起作用。如果您尝试在由于写入转发而不允许使用某个语句的情况下使用该语句,则会看到一条类似于以下内容的错误消息:

ERROR 1235 (42000): This version of MySQL doesn't yet support 'operation with write forwarding'.
数据定义语言 (DDL)

连接到写入器数据库实例以运行 DDL 语句。您不能从读取器数据库实例运行它们。

使用临时表中的数据更新永久表

您可以在启用写入转发的数据库集群上使用临时表。但是,如果语句引用临时表,则不能使用 DML 语句来修改永久表。例如,您不能使用从临时表中获取数据的 INSERT ... SELECT 语句。

XA 事务

在会话内启用写入转发时,不能在数据库集群上使用以下语句。您可以在未启用写入转发的数据库集群上使用这些语句,或者在 aurora_replica_read_consistency 设置为空的会话中使用这些语句。在会话内启用写入转发之前,请检查您的代码是否使用这些语句。

XA {START|BEGIN} xid [JOIN|RESUME] XA END xid [SUSPEND [FOR MIGRATE]] XA PREPARE xid XA COMMIT xid [ONE PHASE] XA ROLLBACK xid XA RECOVER [CONVERT XID]
永久表的 LOAD 语句

您不能在启用写入转发的数据库集群上使用以下语句。

LOAD DATA INFILE 'data.txt' INTO TABLE t1; LOAD XML LOCAL INFILE 'test.xml' INTO TABLE t1;
插件语句

您不能在启用写入转发的数据库集群上使用以下语句。

INSTALL PLUGIN example SONAME 'ha_example.so'; UNINSTALL PLUGIN example;
SAVEPOINT 语句

在会话内启用写入转发时,不能在数据库集群上使用以下语句。您可以在未启用写入转发的数据库集群上使用这些语句,或者在 aurora_replica_read_consistency 设置为空白的会话中使用这些语句。在会话内启用写入转发之前,请检查您的代码是否使用这些语句。

SAVEPOINT t1_save; ROLLBACK TO SAVEPOINT t1_save; RELEASE SAVEPOINT t1_save;

写入转发的隔离级别

在使用写入转发的会话中,您只能使用 REPEATABLE READ 隔离级别。尽管您也可以将 READ COMMITTED 隔离级别用于 Aurora 副本,但该隔离级别不适用于写入转发。有关 REPEATABLE READREAD COMMITTED 隔离级别的信息,请参阅 Aurora MySQL 隔离级别

写入转发的读取一致性

您可以控制数据库集群上的读取一致性程度。读取一致性级别确定数据库集群在每次读取操作之前要等待多少时间,以确保从主集群复制某些或所有更改。您可以调整读取一致性级别,以确保会话中所有转发的写入操作在数据库集群中都可见,然后再进行任何后续查询。您还可以使用此设置来确保数据库集群上的查询始终看到来自写入器的最新更新。此设置也适用于其他会话或其他集群提交的查询。要为应用程序指定此类行为,请为 aurora_replica_read_consistency 数据库参数或数据库集群参数选择一个值。

重要

当您想要转发写入时,请始终设置 aurora_replica_read_consistency 数据库参数或数据库集群参数。否则,Aurora 不会转发写入。默认情况下,此参数的值为空,因此在使用此参数时请选择一个特定值。aurora_replica_read_consistency 参数仅影响启用了写入转发的数据库集群或实例。

如果您提高一致性级别,您的应用程序会花更多时间等待在数据库实例之间传播更改。您可以在快速响应时间与确保在运行查询之前在其他数据库实例中进行的更改完全可用之间选择平衡。

您可以为 aurora_replica_read_consistency 参数指定以下值:

  • EVENTUAL – 在对写入器数据库实例执行写入操作之前,同一会话中写入操作的结果是不可见的。查询不会等待更新的结果可用。因此,它可能会检索较旧的数据或更新的数据,具体取决于语句的时间和复制滞后量。这与不使用写入转发的 Aurora MySQL 数据库集群的一致性相同。

  • SESSION – 所有使用写入转发的查询都会看到在该会话中进行的所有更改的结果。无论事务是否已提交,这些更改都是可见的。如有必要,查询将等待要复制的转发写入操作的结果。

  • GLOBAL – 会话看到数据库集群中所有会话和实例上的所有已提交更改。每个查询可能会等待一段时间,该时间取决于会话滞后量。从查询开始时,如果数据库集群处于最新状态(具有来自写入器的所有已提交数据),查询将继续进行。

有关写入转发涉及的配置参数的信息,请参阅写入转发的配置参数

注意

您也可以使用 aurora_replica_read_consistency 作为会话变量,例如:

mysql> set aurora_replica_read_consistency = 'session';

使用写入转发的示例

以下示例显示了 aurora_replica_read_consistency 参数对运行 INSERT 语句后跟 SELECT 语句的影响。根据 aurora_replica_read_consistency 的值和语句的时间,结果可能会有所不同。

为了实现更高的一致性,您可以在发出 SELECT 语句之前稍等一会。或者,Aurora 可以自动等到结果复制完成后再继续进行 SELECT

有关设置数据库参数的信息,请参阅使用参数组

aurora_replica_read_consistency 设置为 EVENTUAL

运行一个 INSERT 语句,紧接着运行一个 SELECT 语句,将返回一个 COUNT(*) 值,其中包含插入新行之前的行数。稍后再次运行 SELECT 将返回更新的行计数。这些 SELECT 语句不会等待。

mysql> select count(*) from t1; +----------+ | count(*) | +----------+ | 5 | +----------+ 1 row in set (0.00 sec) mysql> insert into t1 values (6); select count(*) from t1; +----------+ | count(*) | +----------+ | 5 | +----------+ 1 row in set (0.00 sec) mysql> select count(*) from t1; +----------+ | count(*) | +----------+ | 6 | +----------+ 1 row in set (0.00 sec)
aurora_replica_read_consistency 设置为 SESSION

紧随 INSERT 后的一条 SELECT 语句会等到 INSERT 语句中的更改变为可见。后续 SELECT 语句不会等待。

mysql> select count(*) from t1; +----------+ | count(*) | +----------+ | 6 | +----------+ 1 row in set (0.01 sec) mysql> insert into t1 values (6); select count(*) from t1; select count(*) from t1; Query OK, 1 row affected (0.08 sec) +----------+ | count(*) | +----------+ | 7 | +----------+ 1 row in set (0.37 sec) +----------+ | count(*) | +----------+ | 7 | +----------+ 1 row in set (0.00 sec)

当读取一致性设置仍设置为 SESSION,如果在执行一条 INSERT 语句后引入简短的等待,则会使更新的行计数在下一条 SELECT 语句运行时可用。

mysql> insert into t1 values (6); select sleep(2); select count(*) from t1; Query OK, 1 row affected (0.07 sec) +----------+ | sleep(2) | +----------+ | 0 | +----------+ 1 row in set (2.01 sec) +----------+ | count(*) | +----------+ | 8 | +----------+ 1 row in set (0.00 sec)
aurora_replica_read_consistency 设置为 GLOBAL

在执行查询之前,每条 SELECT 语句都会等待,截至该语句开始时的所有数据更改均可见。每条 SELECT 语句的等待时间各不相同,具体取决于复制滞后。

mysql> select count(*) from t1; +----------+ | count(*) | +----------+ | 8 | +----------+ 1 row in set (0.75 sec) mysql> select count(*) from t1; +----------+ | count(*) | +----------+ | 8 | +----------+ 1 row in set (0.37 sec) mysql> select count(*) from t1; +----------+ | count(*) | +----------+ | 8 | +----------+ 1 row in set (0.66 sec)

运行带写入转发的多部分语句

DML 语句可能由多个部分组成,如 INSERT ... SELECT 语句或 DELETE ... WHERE 语句。在这种情况下,整个语句将转发到写入器数据库实例并在此处运行。

使用写入转发的事务

如果事务访问模式设置为只读,则不使用写入转发。您可以使用 SET TRANSACTION 语句或 START TRANSACTION 语句指定事务的访问模式。您还可以通过更改 transaction_read_only 会话变量的值来指定事务访问模式。只有在连接到启用了写入转发的数据库集群时,才能更改此会话值。

如果长时间运行的事务在很长一段时间内没有发出任何语句,则可能会超过空闲超时期限。此时段的默认值为一分钟。您可以设置 aurora_fwd_writer_idle_timeout 参数以将其增加到最多一天。超过空闲超时的事务将被写入器实例取消。您提交的下一个后续语句会收到超时错误。然后 Aurora 回滚事务。

在写入转发变得不可用的其他情况下,可能会发生此类错误。例如,如果您重启数据库集群或禁用写入转发,则 Aurora 取消使用写入转发的任何事务。

当使用本地写入转发的集群中的写入器实例重启时,使用本地写入转发的读取器实例上任何活跃的转发事务和查询都将自动关闭。在写入器实例再次可用后,您可以重试这些事务。

写入转发的配置参数

Aurora 数据库参数组包含写入转发功能的设置。下表汇总了有关这些参数的详细信息,表后附有使用说明。

参数 范围 类型 默认值 有效值
aurora_fwd_writer_idle_timeout 集群 无符号整数 60 1–86,400
aurora_fwd_writer_max_connections_pct 集群 无符号长整数 10 0–90
aurora_replica_read_consistency 集群或实例 枚举 ''(null) EVENTUAL, SESSION, GLOBAL

要控制传入的写入请求,请使用以下设置:

  • aurora_fwd_writer_idle_timeout – 写入器数据库实例在关闭从读取器实例转发的连接之前等待此连接上的活动的秒数。如果会话在此期间之后仍处于空闲状态,则 Aurora 取消会话。

  • aurora_fwd_writer_max_connections_pct – 可以在写入器数据库实例上用于处理从读取器实例转发的查询的数据库连接的上限。它表示为写入器的 max_connections 设置的百分比。例如,如果 max_connections 是 800,而 aurora_fwd_master_max_connections_pctaurora_fwd_writer_max_connections_pct 是 10,则写入器最多允许 80 个同时转发会话。这些连接来自由 max_connections 设置管理的同一连接池。

    此设置仅适用于启用了写入转发的写入器。如果减小该值,不会影响现有连接。Aurora 尝试从数据库集群创建新连接时,会考虑账户设置的新值。默认值为 10,表示 max_connections 值的 10%。

注意

由于 aurora_fwd_writer_idle_timeoutaurora_fwd_writer_max_connections_pct 是数据库集群参数,因此每个集群中的所有数据库实例对于这些参数都具有相同的值。

有关 aurora_replica_read_consistency 的更多信息,请参阅 写入转发的读取一致性

有关数据库参数组的更多信息,请参阅 使用参数组

用于写入转发的 Amazon CloudWatch 指标和 Aurora MySQL 状态变量

当您在一个或多个数据库集群上使用写入转发时,以下 Amazon CloudWatch 指标和 Aurora MySQL 状态变量适用。这些指标和状态变量都是在写入器数据库实例上测量的。

CloudWatch 指标 Aurora MySQL 状态变量 单位 描述

ForwardingWriterDMLLatency

毫秒

在写入器数据库实例上处理每个转发的 DML 语句的平均时间。

它不包括数据库集群转发写入请求的时间,也不包括将更改复制回写入器的时间。

ForwardingWriterDMLThroughput

每秒计数 此写入器数据库实例每秒处理的转发 DML 语句数。

ForwardingWriterOpenSessions

Aurora_fwd_writer_open_sessions 计数 写入器数据库实例上的转发会话数。

Aurora_fwd_writer_dml_stmt_count 计数 转发到此写入器数据库实例的 DML 语句总数。

Aurora_fwd_writer_dml_stmt_duration 微秒 转发到此写入器数据库实例的 DML 语句的总持续时间。

Aurora_fwd_writer_select_stmt_count 计数 转发到此写入器数据库实例的 SELECT 语句总数。

Aurora_fwd_writer_select_stmt_duration 微秒 转发到此写入器数据库实例的 SELECT 语句的总持续时间。

以下 CloudWatch 指标和 Aurora MySQL 状态变量是在启用写入转发的数据库集群中的每个读取器数据库实例上测量的。

CloudWatch 指标 Aurora MySQL 状态变量 单位 描述

ForwardingReplicaDMLLatency

毫秒 副本上转发 DML 的平均响应时间。

ForwardingReplicaDMLThroughput

每秒计数 每秒处理的转发 DML 语句数。

ForwardingReplicaOpenSessions

Aurora_fwd_replica_open_sessions 计数 在读取器数据库实例上使用写入转发的会话数。

ForwardingReplicaReadWaitLatency

毫秒

读取器数据库实例上的 SELECT 语句等待赶上写入器的平均等待时间。

读取器数据库实例在处理查询之前等待的程度取决于 aurora_replica_read_consistency 设置。

ForwardingReplicaReadWaitThroughput

每秒计数 转发写入的所有会话中每秒处理的 SELECT 语句总数。

ForwardingReplicaSelectLatency

毫秒 已转发的 SELECT 延迟,监控期间内所有转发 SELECT 语句的平均值。

ForwardingReplicaSelectThroughput

每秒计数 已转发 SELECT 吞吐量,监控期内每秒平均值。

Aurora_fwd_replica_dml_stmt_count 计数 从此读取器数据库实例转发的 DML 语句总数。

Aurora_fwd_replica_dml_stmt_duration 微秒 从此读取器数据库实例转发的所有 DML 语句的总持续时间。

Aurora_fwd_replica_errors_session_limit 计数

由于以下错误条件之一而被主集群拒绝的会话数。

  • 写入器已满

  • 正在转发的语句过多

Aurora_fwd_replica_read_wait_count 计数 此读取器数据库实例上的写入后读取等待的总数。

Aurora_fwd_replica_read_wait_duration 微秒 由于此读取器数据库实例上的读取一致性设置而导致的总等待持续时间。

Aurora_fwd_replica_select_stmt_count 计数 从此读取器数据库实例转发的 SELECT 语句总数。

Aurora_fwd_replica_select_stmt_duration 微秒 从此读取器数据库实例转发的 SELECT 语句的总持续时间。

识别转发的事务和查询

可以使用 information_schema.aurora_forwarding_processlist 表来识别转发的事务和查询。有关此表的更多信息,请参阅 information_schema.aurora_forwarding_processlist

以下示例显示了写入器数据库实例上的所有转发连接。

mysql> select * from information_schema.AURORA_FORWARDING_PROCESSLIST where IS_FORWARDED=1 order by REPLICA_SESSION_ID; +-----+----------+--------------------+----------+---------+------+--------------+--------------------------------------------+--------------+--------------------+---------------------------------+----------------------+----------------+ | ID | USER | HOST | DB | COMMAND | TIME | STATE | INFO | IS_FORWARDED | REPLICA_SESSION_ID | REPLICA_INSTANCE_IDENTIFIER | REPLICA_CLUSTER_NAME | REPLICA_REGION | +-----+----------+--------------------+----------+---------+------+--------------+--------------------------------------------+--------------+--------------------+---------------------------------+---------------------------------------+ | 648 | myuser | IP_address:port1 | sysbench | Query | 0 | async commit | UPDATE sbtest58 SET k=k+1 WHERE id=4802579 | 1 | 637 | my-db-cluster-instance-2 | my-db-cluster | us-west-2 | | 650 | myuser | IP_address:port2 | sysbench | Query | 0 | async commit | UPDATE sbtest54 SET k=k+1 WHERE id=2503953 | 1 | 639 | my-db-cluster-instance-2 | my-db-cluster | us-west-2 | +-----+----------+--------------------+----------+---------+------+--------------+--------------------------------------------+--------------+--------------------+---------------------------------+----------------------+----------------+

在转发读取器数据库实例上,您可以通过运行 SHOW PROCESSLIST 来查看与这些写入器数据库连接关联的线程。写入器上的 REPLICA_SESSION_ID 值 637 和 639 与读取器上的 Id 值相同。

mysql> select @@aurora_server_id; +---------------------------------+ | @@aurora_server_id | +---------------------------------+ | my-db-cluster-instance-2 | +---------------------------------+ 1 row in set (0.00 sec) mysql> show processlist; +-----+----------+--------------------+----------+---------+------+--------------+---------------------------------------------+ | Id | User | Host | db | Command | Time | State | Info | +-----+----------+--------------------+----------+---------+------+--------------+---------------------------------------------+ | 637 | myuser | IP_address:port1 | sysbench | Query | 0 | async commit | UPDATE sbtest12 SET k=k+1 WHERE id=4802579 | | 639 | myuser | IP_address:port2 | sysbench | Query | 0 | async commit | UPDATE sbtest61 SET k=k+1 WHERE id=2503953 | +-----+----------+--------------------+----------+---------+------+--------------+---------------------------------------------+ 12 rows in set (0.00 sec)