为什么我会在 Amazon Aurora 数据库集群发生故障转移后收到只读错误?

1 分钟阅读
0

我使用的是 Amazon Aurora 数据库集群,并且在故障转移后收到以下错误消息: “The MySQL server is running with the --read-only option so it cannot execute this statement”(MySQL 服务器在使用 --read-only 选项运行,因此无法执行此语句) 如何解决此错误?

简短描述

当 Amazon Aurora 数据库集群遇到多可用区故障转移时,集群终端节点会自动更新以反映并指向新指定的写入器和读取器角色。旧的写入器将重新启动,然后在现有副本提升为写入器时被设置为只读模式。

如果收到只读错误消息,则意味着您正在尝试通过具有读取器角色的现有节点执行数据定义语言 (DDL)、数据操作语言 (DML) 或数据控制语言 (DCL) 操作。在 Aurora MySQL 中,您可以通过检查 innodb_read_only 变量来确认这一点,如下所示:

mysql> show variables where variable_name='innodb_read_only';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| innodb_read_only | ON    |
+------------------+-------+
1 row in set (0.01 sec)

解决方法

利用集群写入器终端节点

由于 Aurora 集群中数据库实例的角色可能会发生变化,因此最佳实践是使用集群写入器终端节点来确保始终指向最新的写入器。如果您使用数据库实例终端节点或直接 IP 地址,则可能不知道发生了故障转移,如果重新连接到同一台主机,则会收到只读消息。这将阻止您按预期执行任何 DDL/DML 更改。

不要过度缓存 DNS

如果您没有使用智能驱动程序,则在故障转移事件发生后,您将依赖 DNS 记录的更新和传播。Aurora DNS 区域使用 5 秒的短生存时间 (TTL),因此重要的是,您的网络和客户端配置不要进一步增加此时间。DNS 缓存可以发生在架构的多个层级,例如操作系统 (OS)、网络层和应用程序容器。了解这些层级的配置方式非常重要。如果有意外的 DNS 缓存超出了 5 秒的 TTL,则在故障转移之后,您可能会重新连接到旧的写入器。

Java 虚拟机 (JVM) 可以无限期地过度缓存 DNS。当 JVM 将主机名解析为 IP 地址时,它会在一段指定的时间 (TTL) 内缓存 IP 地址。在某些配置中,JVM 默认 TTL 被设置为在重新启动 JVM 之前永不刷新 DNS 条目。这可能会导致故障转移后发生只读错误。在这种情况下,重要的是手动设置一个较小的 TTL,以便它能够定期刷新。

使用智能驱动程序

Amazon Aurora 数据库集群终端节点会自动传播 DNS 记录更新,但该过程不会立即发生。这可能会导致对数据库上发生的事件的响应延迟,并且该事件可能会由应用程序处理。智能驱动程序通过近实时的 INFORMATION_SCHEMA.REPLICA_HOST_STATUS 元数据表使用数据库集群测图。这有助于将连接路由到适当的角色,并有助于在现有副本之间实现负载平衡。MariaDB Connector/J 是第三方智能驱动程序的一个示例,它对 Aurora MySQL 提供本机支持。

注意:即使是智能驱动程序也可能受到过多 DNS 缓存的影响。

测试您连接到哪个实例

正如 Aurora 连接管理手册的最佳实践中所述,在不使用智能驱动程序时,您应该测试并了解在建立新连接后登录的实例。这可以帮助您确保已连接到正确的实例。您可以使用 @@innodb_read_only variable 测试您是否连接到了写入器示例或 Aurora 读取器。此示例显示的值为 0,表示您已连接到写入器。

mysql> select @@innodb_read_only; 
+--------------------+ 
| @@innodb_read_only | 
+--------------------+ 
| 0                  | 
+--------------------+ 
1 row in set (0.00 sec)

相关信息

Amazon Aurora 连接管理

为 DNS 名称查找设置 JVM TTL

DBA 连接管理手册

AWS 官方
AWS 官方已更新 3 年前