

# 在 Amazon Aurora MySQL 数据库集群中使用本地写入转发
<a name="aurora-mysql-write-forwarding"></a>

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

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

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

本地写入转发与全局写入转发不同，后者将写入从辅助数据库集群转发到 Aurora 全局数据库中的主数据库集群。您可以在属于 Aurora 全局数据库的数据库集群中使用本地写入转发。有关更多信息，请参阅 [在 Amazon Aurora Global Database 中使用写入转发](aurora-global-database-write-forwarding.md)。

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

**Topics**
+ [启用本地写入转发](aurora-mysql-write-forwarding-enabling.md)
+ [检查数据库集群是否启用了写入转发](#aurora-mysql-write-forwarding-describing)
+ [应用程序和 SQL 与写入转发的兼容性](#aurora-mysql-write-forwarding-compatibility)
+ [写入转发的隔离级别](#aurora-mysql-write-forwarding-isolation)
+ [写入转发的读取一致性](aurora-mysql-write-forwarding-consistency.md)
+ [运行带写入转发的多部分语句](#aurora-mysql-write-forwarding-multipart)
+ [使用写入转发的事务](#aurora-mysql-write-forwarding-txns)
+ [写入转发的配置参数](#aurora-mysql-write-forwarding-params)
+ [用于写入转发的 Amazon CloudWatch 指标和 Aurora MySQL 状态变量](aurora-mysql-write-forwarding-cloudwatch.md)
+ [识别转发的事务和查询](#aurora-write-forwarding-processlist)

## 检查数据库集群是否启用了写入转发
<a name="aurora-mysql-write-forwarding-describing"></a>

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

在 AWS 管理控制台中，在集群详细信息页面的**配置**选项卡上，您可以看到**本地只读副本写入转发**的状态为**已启用**。

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

**Example**  

```
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 与写入转发的兼容性
<a name="aurora-mysql-write-forwarding-compatibility"></a>

您可以将以下类型的 SQL 语句与写入转发一起使用：
+ 数据操作语言 (DML) 语句，如 `INSERT`、`DELETE` 和 `UPDATE`。对于您可以与写入转发一起使用的这些语句的属性存在一些限制，如下所述。
+ `SELECT ... LOCK IN SHARE MODE` 和 `SELECT FOR UPDATE` 语句。
+ `PREPARE` 和 `EXECUTE` 语句。

在具有写入转发功能的数据库集群中使用某些语句时，不允许这些语句，否则它们可能产生过时的结果。此外，不支持用户定义的函数和用户定义的过程。因此，原定设置情况下，数据库集群的 `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;
```

## 写入转发的隔离级别
<a name="aurora-mysql-write-forwarding-isolation"></a>

在使用写入转发的会话中，您只能使用 `REPEATABLE READ` 隔离级别。尽管您也可以将 `READ COMMITTED` 隔离级别用于 Aurora 副本，但该隔离级别不适用于写入转发。有关 `REPEATABLE READ` 和 `READ COMMITTED` 隔离级别的信息，请参阅 [Aurora MySQL 隔离级别](AuroraMySQL.Reference.IsolationLevels.md)。

## 运行带写入转发的多部分语句
<a name="aurora-mysql-write-forwarding-multipart"></a>

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

## 使用写入转发的事务
<a name="aurora-mysql-write-forwarding-txns"></a>

如果事务访问模式设置为只读，则不使用写入转发。您可以使用 `SET TRANSACTION` 语句或 `START TRANSACTION` 语句指定事务的访问模式。您还可以通过更改 [transaction\$1read\$1only](https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_transaction_read_only) 会话变量的值来指定事务访问模式。只有在连接到启用了写入转发的数据库集群时，才能更改此会话值。

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

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

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

## 写入转发的配置参数
<a name="aurora-mysql-write-forwarding-params"></a>

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


| 参数 | 范围 | 类型 | 默认值 | 有效值 | 
| --- | --- | --- | --- | --- | 
| aurora\$1fwd\$1writer\$1idle\$1timeout | 集群 | 无符号整数 | 60 | 1–86,400 | 
| aurora\$1fwd\$1writer\$1max\$1connections\$1pct | 集群 | 无符号长整数 | 10 | 0–90 | 
| aurora\$1replica\$1read\$1consistency | 集群或实例 | 枚举 | ''（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_pct` 或 `aurora_fwd_writer_max_connections_pct` 是 10，则写入器最多允许 80 个同时转发会话。这些连接来自由 `max_connections` 设置管理的同一连接池。

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

**注意**  
由于 `aurora_fwd_writer_idle_timeout` 和 `aurora_fwd_writer_max_connections_pct` 是数据库集群参数，因此每个集群中的所有数据库实例对于这些参数都具有相同的值。

有关 `aurora_replica_read_consistency` 的更多信息，请参阅 [写入转发的读取一致性](aurora-mysql-write-forwarding-consistency.md)。

有关数据库参数组的更多信息，请参阅 [Amazon Aurora 的参数组](USER_WorkingWithParamGroups.md)。

## 识别转发的事务和查询
<a name="aurora-write-forwarding-processlist"></a>

可以使用 `information_schema.aurora_forwarding_processlist` 表来识别转发的事务和查询。有关此表的更多信息，请参阅 [information\$1schema.aurora\$1forwarding\$1processlist](AuroraMySQL.Reference.ISTables.md#AuroraMySQL.Reference.ISTables.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)
```